From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5929F283C91; Tue, 6 May 2025 15:21:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544895; cv=none; b=n7a2rteL3q6V93NGviAEuFyvcNUMB8rQFwmMV5ApChDJXMBUalCbcynFkKJjZ8BgCsJwBFmFguTzVPaQMLMf4NfWwTg2rGaLGrBWYa4vktOTTWJf75YH4lspoyieFb1b2NEHtImyr/dCHxKjRCZXPHDY0OpxUvG8tG9frXhbSlQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544895; c=relaxed/simple; bh=ArpSGaELRtIcEnBIvydZufpYt2tcyW531ny0FgKVEU0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XO+8GUsvuaKu1FEWzKc390f4HbA2OQDwxPhF6HMrXS7tXdCqvNIOXaynrsliF5Mv5dEt3gH/f1H0+Pjfr3VnOMpUYkgiyDE1+478iLxjSpxSyT+Gs9iYgxOGo59aDC53Bfnq+qjhN5OxPWkNzMTwqOeAdorNeg7ylz4N0QKMIqM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Gqjew4MF; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Gqjew4MF" Received: by mail.gandi.net (Postfix) with ESMTPSA id 926E743B39; Tue, 6 May 2025 15:21:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544886; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vwFqRYJCao11TjqazPLblrbyeF94Ji0bncnET8QI318=; b=Gqjew4MFzYRG59G3QLvlV954CBniwkS/NmSLbgQCuroaqMGRCr+WM1SNVnd5ekoDadOHMe /4E9RuEl2KTdqpUp6NutGChL8n1/8s/OZDanH44MdxTljdfnFmh1PTxT7CFZtWyh/h8JD/ qFxU1SezjKxQg9frrORZHzIO+n2HqAcGgIRMtykrdWC61YJYTfSStzDbcp4hCVOwx9GRxi 3ulD8BOvLArl+6reaz+L6ClVjI80ydJbr6hIyqx31YtOe78BmDyDMTeiTPeFkrVWUr+7Zr AfzEaOMltX7krOctQWGRUYW2Zyd251MZ/gtwDUY4N0aVAHHk4+aAx62864CRtg== From: Thomas Richard Date: Tue, 06 May 2025 17:21:19 +0200 Subject: [PATCH v5 01/12] gpiolib: add support to register sparse pin range 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: <20250506-aaeon-up-board-pinctrl-support-v5-1-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Add support to register for GPIO<->pin mapping using a list of non consecutive pins. The core already supports sparse pin range (pins member of struct pinctrl_gpio_range), but it was not possible to register one. If pins is not NULL the core uses it, otherwise it assumes that a consecutive pin range was registered and it uses pin_base. The function gpiochip_add_pin_range() which allocates and fills the struct pinctrl_gpio_range was renamed to gpiochip_add_pin_range_with_pins() and the pins parameter was added. Two new functions were added, gpiochip_add_pin_range() and gpiochip_add_sparse_pin_range() to register a consecutive or sparse pins range. Both use gpiochip_add_pin_range_with_pins(). Reviewed-by: Linus Walleij Reviewed-by: Andy Shevchenko Signed-off-by: Thomas Richard --- drivers/gpio/gpiolib.c | 29 ++++++++++++++++++-------- include/linux/gpio/driver.h | 51 +++++++++++++++++++++++++++++++++++++++++= +--- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index cd4fecbb41f2..b59fc4d751da 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2283,11 +2283,13 @@ int gpiochip_add_pingroup_range(struct gpio_chip *g= c, EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); =20 /** - * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping + * gpiochip_add_pin_range_with_pins() - add a range for GPIO <-> pin mappi= ng * @gc: the gpiochip to add the range for * @pinctl_name: the dev_name() of the pin controller to map to * @gpio_offset: the start offset in the current gpio_chip number space * @pin_offset: the start offset in the pin controller number space + * @pins: the list of non consecutive pins to accumulate in this range (if= not + * NULL, pin_offset is ignored by pinctrl core) * @npins: the number of pins from the offset of each pin space (GPIO and * pin controller) to accumulate in this range * @@ -2299,9 +2301,12 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); * Returns: * 0 on success, or a negative errno on failure. */ -int gpiochip_add_pin_range(struct gpio_chip *gc, const char *pinctl_name, - unsigned int gpio_offset, unsigned int pin_offset, - unsigned int npins) +int gpiochip_add_pin_range_with_pins(struct gpio_chip *gc, + const char *pinctl_name, + unsigned int gpio_offset, + unsigned int pin_offset, + unsigned int const *pins, + unsigned int npins) { struct gpio_pin_range *pin_range; struct gpio_device *gdev =3D gc->gpiodev; @@ -2319,6 +2324,7 @@ int gpiochip_add_pin_range(struct gpio_chip *gc, cons= t char *pinctl_name, pin_range->range.name =3D gc->label; pin_range->range.base =3D gdev->base + gpio_offset; pin_range->range.pin_base =3D pin_offset; + pin_range->range.pins =3D pins; pin_range->range.npins =3D npins; pin_range->pctldev =3D pinctrl_find_and_add_gpio_range(pinctl_name, &pin_range->range); @@ -2328,16 +2334,21 @@ int gpiochip_add_pin_range(struct gpio_chip *gc, co= nst char *pinctl_name, kfree(pin_range); return ret; } - chip_dbg(gc, "created GPIO range %d->%d =3D=3D> %s PIN %d->%d\n", - gpio_offset, gpio_offset + npins - 1, - pinctl_name, - pin_offset, pin_offset + npins - 1); + if (pin_range->range.pins) + chip_dbg(gc, "created GPIO range %d->%d =3D=3D> %s %d sparse PIN range {= %d, ... }", + gpio_offset, gpio_offset + npins - 1, + pinctl_name, npins, pins[0]); + else + chip_dbg(gc, "created GPIO range %d->%d =3D=3D> %s PIN %d->%d\n", + gpio_offset, gpio_offset + npins - 1, + pinctl_name, + pin_offset, pin_offset + npins - 1); =20 list_add_tail(&pin_range->node, &gdev->pin_ranges); =20 return 0; } -EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); +EXPORT_SYMBOL_GPL(gpiochip_add_pin_range_with_pins); =20 /** * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 4c0294a9104d..6142837ea403 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -784,23 +784,68 @@ struct gpio_pin_range { =20 #ifdef CONFIG_PINCTRL =20 -int gpiochip_add_pin_range(struct gpio_chip *gc, const char *pinctl_name, - unsigned int gpio_offset, unsigned int pin_offset, - unsigned int npins); +int gpiochip_add_pin_range_with_pins(struct gpio_chip *gc, + const char *pinctl_name, + unsigned int gpio_offset, + unsigned int pin_offset, + unsigned int const *pins, + unsigned int npins); int gpiochip_add_pingroup_range(struct gpio_chip *gc, struct pinctrl_dev *pctldev, unsigned int gpio_offset, const char *pin_group); void gpiochip_remove_pin_ranges(struct gpio_chip *gc); =20 +static inline int +gpiochip_add_pin_range(struct gpio_chip *gc, + const char *pinctl_name, + unsigned int gpio_offset, + unsigned int pin_offset, + unsigned int npins) +{ + return gpiochip_add_pin_range_with_pins(gc, pinctl_name, gpio_offset, + pin_offset, NULL, npins); +} + +static inline int +gpiochip_add_sparse_pin_range(struct gpio_chip *gc, + const char *pinctl_name, + unsigned int gpio_offset, + unsigned int const *pins, + unsigned int npins) +{ + return gpiochip_add_pin_range_with_pins(gc, pinctl_name, gpio_offset, 0, + pins, npins); +} #else /* ! CONFIG_PINCTRL */ =20 +static inline int +gpiochip_add_pin_range_with_pins(struct gpio_chip *gc, + const char *pinctl_name, + unsigned int gpio_offset, + unsigned int pin_offset, + unsigned int npins) +{ + return 0; +} + static inline int gpiochip_add_pin_range(struct gpio_chip *gc, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, unsigned int npins) +{ + return 0 +} + +static inline int +gpiochip_add_sparse_pin_range(struct gpio_chip *gc, + const char *pinctl_name, + unsigned int gpio_offset, + unsigned int const *pins, + unsigned int npins) { return 0; } + static inline int gpiochip_add_pingroup_range(struct gpio_chip *gc, struct pinctrl_dev *pctldev, --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95D8B283C9C; Tue, 6 May 2025 15:21:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544896; cv=none; b=crxMcYY92qrpeQj1F3bcSL5KcjiPIvx7NhmEcAOPc7Q7nl7AIFZV/c6F92TR+9OcnXG1EQ/TMrda+Lsv0Hexm/zx4rkwipLWYmDIt5y2Gx8gUSTD1aE8eBAyG3rtxhHUlUbw9RoSBOu0xkDNFb65KmHSeghhM75FNgVX8EGGOgc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544896; c=relaxed/simple; bh=56bTPPIQLXvmsf5LCAJEmK7HEvsdxzS94R86YuQfSm4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FJHd692mx9SeOkC8bfaN3dfeeRvZvYy9AZDMgvFxW2R3P6CzCysj7tVXfie7wug707UkwbyT6WyKeBEtqyz/Qjiq2NVyUF9rueA4H91egvBZsEt53j5xC2B8uv3au0LHNvXk7kWMeZthUmoHE9D3SBcBd1JAf3duTs8cP4CqlmA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=PESKl44y; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="PESKl44y" Received: by mail.gandi.net (Postfix) with ESMTPSA id 2B1A543B14; Tue, 6 May 2025 15:21:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544886; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tMK78815Dg1a0/PXJsktZUNkpbltOz6RRsoWHHtQeSE=; b=PESKl44yc/qxdRkT+sa9wKWPVbjllfX1DMQidHwLf4HWWwtF4fuqUMoUI4L7UCgBCbkEcJ +P3UEjNtz/7fo9dijkFNFqIQ4XR67wdsi+fwBD/2ZJdvPuw9hBjEoK53nmSEVsTQl/yYVw 5vv6WgY7e26it+6v2XfG6YvJJNuhZplAd1AElvPilkhMHH9Ze6ZLs8HvHUfoE7xhmhZR6Z NlS766fl2Uc2/QMTpppyFiaaDhOI0SKoUCFhnanLy7hLhuDwNpde4XApFqqVoPfulLyLRP coW09WqtHrgViL/5juPiaS0ONmXEcH3DD5z9ePWi4asm2K8sOxGPFwR9jEhFDg== From: Thomas Richard Date: Tue, 06 May 2025 17:21:20 +0200 Subject: [PATCH v5 02/12] pinctrl: remove extern specifier for functions in machine.h 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: <20250506-aaeon-up-board-pinctrl-support-v5-2-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Extern is the default specifier for a function, no need to define it. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Thomas Richard Reviewed-by: Linus Walleij --- include/linux/pinctrl/machine.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machin= e.h index 673e96df453b..93aceb92681b 100644 --- a/include/linux/pinctrl/machine.h +++ b/include/linux/pinctrl/machine.h @@ -153,10 +153,9 @@ struct pinctrl_map; =20 #ifdef CONFIG_PINCTRL =20 -extern int pinctrl_register_mappings(const struct pinctrl_map *map, - unsigned int num_maps); -extern void pinctrl_unregister_mappings(const struct pinctrl_map *map); -extern void pinctrl_provide_dummies(void); +int pinctrl_register_mappings(const struct pinctrl_map *map, unsigned int = num_maps); +void pinctrl_unregister_mappings(const struct pinctrl_map *map); +void pinctrl_provide_dummies(void); #else =20 static inline int pinctrl_register_mappings(const struct pinctrl_map *map, --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95CD1283C94; Tue, 6 May 2025 15:21:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544897; cv=none; b=k5WCRZGl2Xa8Wqf9RH12Hx4GKZjKtThWqbZGU2aiWh8cSffDGgUeaG/cWKvm+olEocKAJ1+WslH+1F/zBM3fYd0Zm+qexSHp+DPWE8e6z2+DrJLNedVTKVFEQz+frGtAyefaSYi0uv9ONRjGcKrQl7/q2V+h8nlFSG/0QSmbfk0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544897; c=relaxed/simple; bh=LM2iFEgMbtNke6NMYAqnjE4d+/qvxBKcq5oPNLRfjA0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Fy/d7SG3fz0GYUDOEzNoXv7WXpfa8kdANSz21oZuGYpy0iVBzbXldFXuBM5AzYoO6AY44AMSxSz5tg2vRDy40NH0wxGHPP2UbpOiz9je2I052TOiRs5hyA1cxnVZa2CV+ydNCL37xql7mWg1ETHJC1vd5XugtmbUdXV1bsPTxhw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=nnkmRuVY; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="nnkmRuVY" Received: by mail.gandi.net (Postfix) with ESMTPSA id B0D0A43B27; Tue, 6 May 2025 15:21:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544887; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CvPjKxjylgfhC14NcJPCUvKX8Z1QrI+WRe+JS+bhNVM=; b=nnkmRuVYT0l4wYYi4JuZMftHQmT1K7YQSlMY1DlwI9D+BlEpIUTPjRzEovxTtXB3YlZ8x7 hH/GbQpxbAfhaswec9u1kvALPuUrPMBkWwyPGMz/j1cEYyqdHY7cAYdR43MJUEp5nIa/Mg RzwK8wS3HKq9vSBF5QJ8sbNIwRPdNo/LRRt0GPEZRFrN2lJ26TV/CWPzL0UySD9Ro4kJOq UCNHFnmPbpfLJtLashPyYmWmehBPDAThSIR+LQMsutPJDJbojdCPhtxQaqlUdZouWmNwWJ kiTEJFP6vCb+g7xd5nRqWKCh/YPSHm3socoyF5dq3EXWlD4yO5z6T6hBpsS0sw== From: Thomas Richard Date: Tue, 06 May 2025 17:21:21 +0200 Subject: [PATCH v5 03/12] pinctrl: core: add devm_pinctrl_register_mappings() 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: <20250506-aaeon-up-board-pinctrl-support-v5-3-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Using devm_pinctrl_register_mappings(), the core can automatically unregister pinctrl mappings. Reviewed-by: Linus Walleij Signed-off-by: Thomas Richard --- drivers/pinctrl/core.c | 29 +++++++++++++++++++++++++++++ include/linux/pinctrl/machine.h | 11 +++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 4bdbf6bb26e2..9046292d1360 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1530,6 +1530,35 @@ void pinctrl_unregister_mappings(const struct pinctr= l_map *map) } EXPORT_SYMBOL_GPL(pinctrl_unregister_mappings); =20 +static void devm_pinctrl_unregister_mappings(void *maps) +{ + pinctrl_unregister_mappings(maps); +} + +/** + * devm_pinctrl_register_mappings() - Resource managed pinctrl_register_ma= ppings() + * @dev: device for which mappings are registered + * @maps: the pincontrol mappings table to register. Note the pinctrl-core + * keeps a reference to the passed in maps, so they should _not_ be + * marked with __initdata. + * @num_maps: the number of maps in the mapping table + * + * Returns: 0 on success, or negative errno on failure. + */ +int devm_pinctrl_register_mappings(struct device *dev, + const struct pinctrl_map *maps, + unsigned int num_maps) +{ + int ret; + + ret =3D pinctrl_register_mappings(maps, num_maps); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, devm_pinctrl_unregister_mappings, (v= oid *)maps); +} +EXPORT_SYMBOL_GPL(devm_pinctrl_register_mappings); + /** * pinctrl_force_sleep() - turn a given controller device into sleep state * @pctldev: pin controller device diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machin= e.h index 93aceb92681b..00c196061605 100644 --- a/include/linux/pinctrl/machine.h +++ b/include/linux/pinctrl/machine.h @@ -149,11 +149,15 @@ struct pinctrl_map { #define PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(dev, grp, cfgs) \ PIN_MAP_CONFIGS_GROUP(dev, PINCTRL_STATE_DEFAULT, dev, grp, cfgs) =20 +struct device; struct pinctrl_map; =20 #ifdef CONFIG_PINCTRL =20 int pinctrl_register_mappings(const struct pinctrl_map *map, unsigned int = num_maps); +int devm_pinctrl_register_mappings(struct device *dev, + const struct pinctrl_map *map, + unsigned int num_maps); void pinctrl_unregister_mappings(const struct pinctrl_map *map); void pinctrl_provide_dummies(void); #else @@ -164,6 +168,13 @@ static inline int pinctrl_register_mappings(const stru= ct pinctrl_map *map, return 0; } =20 +static inline int devm_pinctrl_register_mappings(struct device *dev, + const struct pinctrl_map *map, + unsigned int num_maps) +{ + return 0; +} + static inline void pinctrl_unregister_mappings(const struct pinctrl_map *m= ap) { } --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F03F283C8D; Tue, 6 May 2025 15:21:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544897; cv=none; b=fuIaN/djLKeTvfOEYZAI89zugBBSFJFtZQ9uEeSyTQY/oKKWWWRl91LjfB/YLQ4ZrSPU9yymjzThnAbETlaSrxtTdAgJne2CGUV84vdwx4enjL7v9JSt0NkBLUQOsG/06X1XGF0f+ldOF/99zZ8g+0JmuX14LXy2WTDGNSo6Ex4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544897; c=relaxed/simple; bh=w4N7KqRA8Nlo0iFeeW1pPDRKcPmWnBcx7ukfAQkiz5k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EMYLmpnaRXDDNXplFDxNnunoj8jKE80pFfYVVtSFQ+JzCAmx0RTSbP5CcLv5BMbh0/T4pu8qcya2LNcglu+XWndwVFa3IxQcT4NvJuAxh8qH6gvwhM2VU3onyOe+yW+tiXj7EZSfyH8WsxHgNfAq3SGYeLMSPW0RcE6erALsFZk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=QT961ZCS; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="QT961ZCS" Received: by mail.gandi.net (Postfix) with ESMTPSA id 3F0AB43B3A; Tue, 6 May 2025 15:21:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544887; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uG8S/JidauisAuQdchy3W96wedqpyUbkFYJXuGX6xqw=; b=QT961ZCSK1vzKE4MYo6VfI2fkXTQNqHm+N4u5BPjJqkOB+yTPGbF8uu8aywL5jT+QvLkeW PZ53zwvY/bv2yrakKIJrEN5uTE8oQPKBDH//ro4T+tT6e8OyEh3Nn6eV5ExFdQ6+W94Yfy KebmXR6pM63cIaDjvRgrLIAtRw5xAvjlAcJndivGhntsqH+KIa+gasP+whk7fznEwkT3Jw rWspkwiWSm5AMk4J3+5geX+XukMBxO6+rq00EmZ/s/WQCt0hEZ+5zwP4DQfZAaWDeaHENE l6LtyFozZc6ccpbIINjOVFRKTErjejpWOJQUV1ijWBdX8DOGVBILjxDBFD8Vlw== From: Thomas Richard Date: Tue, 06 May 2025 17:21:22 +0200 Subject: [PATCH v5 04/12] gpio: aggregator: move GPIO forwarder allocation in a dedicated function 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: <20250506-aaeon-up-board-pinctrl-support-v5-4-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Move the GPIO forwarder allocation and static initialization in a dedicated function. Reviewed-by: Andy Shevchenko Signed-off-by: Thomas Richard --- drivers/gpio/gpio-aggregator.c | 47 ++++++++++++++++++++++++++++----------= ---- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index d232ea865356..4268ef94914d 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -498,6 +498,36 @@ static int gpiochip_fwd_setup_delay_line(struct device= *dev, struct gpio_chip *c } #endif /* !CONFIG_OF_GPIO */ =20 +static struct gpiochip_fwd * +devm_gpiochip_fwd_alloc(struct device *dev, unsigned int ngpios) +{ + const char *label =3D dev_name(dev); + struct gpiochip_fwd *fwd; + struct gpio_chip *chip; + + fwd =3D devm_kzalloc(dev, struct_size(fwd, tmp, fwd_tmp_size(ngpios)), GF= P_KERNEL); + if (!fwd) + return ERR_PTR(-ENOMEM); + + chip =3D &fwd->chip; + + chip->label =3D label; + chip->parent =3D dev; + chip->owner =3D THIS_MODULE; + chip->get_direction =3D gpio_fwd_get_direction; + chip->direction_input =3D gpio_fwd_direction_input; + chip->direction_output =3D gpio_fwd_direction_output; + chip->get =3D gpio_fwd_get; + chip->get_multiple =3D gpio_fwd_get_multiple_locked; + chip->set_rv =3D gpio_fwd_set; + chip->set_multiple_rv =3D gpio_fwd_set_multiple_locked; + chip->to_irq =3D gpio_fwd_to_irq; + chip->base =3D -1; + chip->ngpio =3D ngpios; + + return fwd; +} + /** * gpiochip_fwd_create() - Create a new GPIO forwarder * @dev: Parent device pointer @@ -518,14 +548,12 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struc= t device *dev, struct gpio_desc *descs[], unsigned long features) { - const char *label =3D dev_name(dev); struct gpiochip_fwd *fwd; struct gpio_chip *chip; unsigned int i; int error; =20 - fwd =3D devm_kzalloc(dev, struct_size(fwd, tmp, fwd_tmp_size(ngpios)), - GFP_KERNEL); + fwd =3D devm_gpiochip_fwd_alloc(dev, ngpios); if (!fwd) return ERR_PTR(-ENOMEM); =20 @@ -549,19 +577,6 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct= device *dev, chip->set_config =3D gpio_fwd_set_config; } =20 - chip->label =3D label; - chip->parent =3D dev; - chip->owner =3D THIS_MODULE; - chip->get_direction =3D gpio_fwd_get_direction; - chip->direction_input =3D gpio_fwd_direction_input; - chip->direction_output =3D gpio_fwd_direction_output; - chip->get =3D gpio_fwd_get; - chip->get_multiple =3D gpio_fwd_get_multiple_locked; - chip->set_rv =3D gpio_fwd_set; - chip->set_multiple_rv =3D gpio_fwd_set_multiple_locked; - chip->to_irq =3D gpio_fwd_to_irq; - chip->base =3D -1; - chip->ngpio =3D ngpios; fwd->descs =3D descs; =20 if (chip->can_sleep) --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F45C283CB5; Tue, 6 May 2025 15:21:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544897; cv=none; b=UB/9yvHmUV/VHSXzayT1ze0JT/+ew+QZlXOu48hKkHDJvxIXbzgJVaLyaI8ceZgMirgY+D3ytkGzq2kwgwCEKCXaq66BqEcBENIUHXATPSH0jYP9JrN6eZzK8iTRoKOj7XaU2J/X9Hb6PJJBHpaX3+xklOpdbhB7BhaIJSrFdp8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544897; c=relaxed/simple; bh=Uw49RaTelOrwOk+FJrDe4DnxOi4wzzFKqU803pdfICs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CfxjANYO7RnqKGwrDfjvKUr9Fbq+q4KO62MXw0a+OzfxmdmSZUwDM2pqXPzwwkFx816dRjtxPS7GlITU8+rBANuDEKVU3wgnQG5geNm5nNpUlt7SZjV/mLxrGRrkBKcLxj87Wn0bEhYZlSQUYfDUxcgNeLNXx5zNHR+KbCG7x1U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=K/k4OVkj; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="K/k4OVkj" Received: by mail.gandi.net (Postfix) with ESMTPSA id C8E5C43B37; Tue, 6 May 2025 15:21:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544888; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9Q4UReFmn4Pspd3+GoPvOwnJiwMV0hCxt4+MCuhAowQ=; b=K/k4OVkjBIe0UmGom7wiMy/l533oL7psrRqLWsETaK55AXOxjT7wz9yAnaUfbrnhenvA9t qLVPEFBu2eXvCH3dXSC9/ILA6bhBEL98lNWkAhdVJPJ+W/Knb+Xszb3RG0iF9iKjIsYubs BX4Z2UJm7LujApqa/IxtHklN9uxzADENFvnh9Fre+6NieSasb6tVpa3MZp4AEX1quqnTyQ x46/Wl2xFZF/TKwtw9e0OPrpnWgBakvcsX8j8AJkHlM9X2eAqxVK5Sg0h87WXA3kaTy7h2 N1Gki9ZUF5KSpofUTXjvNHhdJqyxY7km+4PVxWwpvAlw+CJYSqVuIWb0pfxGrw== From: Thomas Richard Date: Tue, 06 May 2025 17:21:23 +0200 Subject: [PATCH v5 05/12] gpio: aggregator: refactor the code to add GPIO desc in the forwarder 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: <20250506-aaeon-up-board-pinctrl-support-v5-5-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Create a dedicated function to add a GPIO desc in the forwarder. Instead of passing an array of GPIO descs, now the GPIO descs are passed on by one to the forwarder. Signed-off-by: Thomas Richard Reviewed-by: Andy Shevchenko --- drivers/gpio/gpio-aggregator.c | 54 +++++++++++++++++++++++++++++---------= ---- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 4268ef94914d..7ca6f1953938 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -509,6 +509,10 @@ devm_gpiochip_fwd_alloc(struct device *dev, unsigned i= nt ngpios) if (!fwd) return ERR_PTR(-ENOMEM); =20 + fwd->descs =3D devm_kcalloc(dev, ngpios, sizeof(*fwd->descs), GFP_KERNEL); + if (!fwd->descs) + return ERR_PTR(-ENOMEM); + chip =3D &fwd->chip; =20 chip->label =3D label; @@ -528,6 +532,36 @@ devm_gpiochip_fwd_alloc(struct device *dev, unsigned i= nt ngpios) return fwd; } =20 +static int gpiochip_fwd_gpio_add(struct gpiochip_fwd *fwd, + struct gpio_desc *desc, + unsigned int offset) +{ + struct gpio_chip *parent =3D gpiod_to_chip(desc); + struct gpio_chip *chip =3D &fwd->chip; + + if (offset > chip->ngpio) + return -EINVAL; + + /* + * If any of the GPIO lines are sleeping, then the entire forwarder + * will be sleeping. + * If any of the chips support .set_config(), then the forwarder will + * support setting configs. + */ + if (gpiod_cansleep(desc)) + chip->can_sleep =3D true; + + if (parent && parent->set_config) + chip->set_config =3D gpio_fwd_set_config; + + fwd->descs[offset] =3D desc; + + dev_dbg(chip->parent, "%u =3D> gpio %d irq %d\n", offset, + desc_to_gpio(desc), gpiod_to_irq(desc)); + + return 0; +} + /** * gpiochip_fwd_create() - Create a new GPIO forwarder * @dev: Parent device pointer @@ -559,26 +593,12 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struc= t device *dev, =20 chip =3D &fwd->chip; =20 - /* - * If any of the GPIO lines are sleeping, then the entire forwarder - * will be sleeping. - * If any of the chips support .set_config(), then the forwarder will - * support setting configs. - */ for (i =3D 0; i < ngpios; i++) { - struct gpio_chip *parent =3D gpiod_to_chip(descs[i]); - - dev_dbg(dev, "%u =3D> gpio %d irq %d\n", i, - desc_to_gpio(descs[i]), gpiod_to_irq(descs[i])); - - if (gpiod_cansleep(descs[i])) - chip->can_sleep =3D true; - if (parent && parent->set_config) - chip->set_config =3D gpio_fwd_set_config; + error =3D gpiochip_fwd_gpio_add(fwd, descs[i], i); + if (error) + return ERR_PTR(error); } =20 - fwd->descs =3D descs; - if (chip->can_sleep) mutex_init(&fwd->mlock); else --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 902BA283FE4; Tue, 6 May 2025 15:21:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544899; cv=none; b=EnjoRlu/iK4mhuy49Hp1yGwMojYTpJXwo2wzh4eeohjfj0OeSWPLTpbobM5ZHRDyhupldwTxwzDfpv2r7yWXesaEZge7W2EKePt71iY4fkOzTyMZ2wzWye+9Be80XgZhjNws/+vzJLG8ZnmXROo1dRfZ09Zofb8I80RV5K7eLWA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544899; c=relaxed/simple; bh=FrF+x8BXuB0x2uiOVL4brq6quyd2XvR136SddU+/B8c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Rmn9nuYsbiYa73KpsYDUQ4qu9N6lb8+yD4ZacsyZ3xdnTBFLap3+fRPBp2yCj66XN6hzyn1yz28+q9Hr+hro7nYeb8zGUXnUVsgXT6QLSl7pLK41uyCKMph2wQBdpQln5v2xEsXVfwPomlYJdKPWn9n95KCqJ5vf+TdL30v7Uhc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=pvpKwyCw; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="pvpKwyCw" Received: by mail.gandi.net (Postfix) with ESMTPSA id 5FD3B43B3C; Tue, 6 May 2025 15:21:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544888; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KJmYwkC5dfaXwizR3nKAIJBi6ydXI5RylfPlIbP47vI=; b=pvpKwyCwaJpHdQ2wylANo15baQ9TtB7+lfLncvgLXrbbLB7/XgCCjWOBAugLBFU326iO8G A7ZNZCVudJ4bd8MYxfjVMvQ+2iAlAY67rthI+LBG0CJ7K2Ad9V+YkqtdmlBQIyEhiAw/KG un1qCNknnOwrvVttNl+iWQ/P2MPxsEjzYQmPresIdzaPpjTDIjCwZkh1iBzyqs75FYJtM7 WWdmOEPsEHbFcUBjPSGCY2P4UgaBWB79v9mREpiCRDBR4kb8RHbz4sWA9xrK+5XrI9Cd8b +QWglrGEx8GFBCzKE243+wxF3qsvlGzqMcE+T/K6kRnTe1u/0ROJGCah0WjU9A== From: Thomas Richard Date: Tue, 06 May 2025 17:21:24 +0200 Subject: [PATCH v5 06/12] gpio: aggregator: refactor the forwarder registration part 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: <20250506-aaeon-up-board-pinctrl-support-v5-6-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Add a new function gpiochip_fwd_register(), which finalizes the initialization of the forwarder and registers the corresponding gpiochip. Reviewed-by: Andy Shevchenko Signed-off-by: Thomas Richard Reviewed-by: Geert Uytterhoeven --- drivers/gpio/gpio-aggregator.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 7ca6f1953938..569c7e8ea4c2 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -562,6 +562,18 @@ static int gpiochip_fwd_gpio_add(struct gpiochip_fwd *= fwd, return 0; } =20 +static int gpiochip_fwd_register(struct gpiochip_fwd *fwd) +{ + struct gpio_chip *chip =3D &fwd->chip; + + if (chip->can_sleep) + mutex_init(&fwd->mlock); + else + spin_lock_init(&fwd->slock); + + return devm_gpiochip_add_data(chip->parent, chip, fwd); +} + /** * gpiochip_fwd_create() - Create a new GPIO forwarder * @dev: Parent device pointer @@ -599,18 +611,13 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struc= t device *dev, return ERR_PTR(error); } =20 - if (chip->can_sleep) - mutex_init(&fwd->mlock); - else - spin_lock_init(&fwd->slock); - if (features & FWD_FEATURE_DELAY) { error =3D gpiochip_fwd_setup_delay_line(dev, chip, fwd); if (error) return ERR_PTR(error); } =20 - error =3D devm_gpiochip_add_data(dev, chip, fwd); + error =3D gpiochip_fwd_register(fwd); if (error) return ERR_PTR(error); =20 --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90408283FE5; Tue, 6 May 2025 15:21:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544898; cv=none; b=WQZes+QHfcNBAZaB3SZ16chQRMG/MuCYa7miYxFtNA+2kd/Eo7jdbFkTOQagO63mSKKjBb5tjd+ODH2ewpBIeKWzu9Zj519IuFZb10ove8q8yRDRk5H/yzgTi298eQ7LHl3BECXiWOqlOZalBh8CmngJxZASayvmP3t4fJc3l/I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544898; c=relaxed/simple; bh=iv61JMvvUiIOu2CMpi/2ShkbCrMG+LUEPG9U4pGtxfY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EzH1kcDmqxXdy9FRnZLe7cSyNoKGn0eG5HXaEI977aUgDwtvpFnLXEguYtzemPLPArNEJL/LmizMf7SuAZVHzaOAgSZ4wymTiov0jumILBlhTn0OEMwRxxGlGUuECblsO0/qXxFgt3UIXQzdMcL2XQaW2uTUmU6+Vvdd3Bn9TlM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=nB07bYSx; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="nB07bYSx" Received: by mail.gandi.net (Postfix) with ESMTPSA id EA3C043B33; Tue, 6 May 2025 15:21:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544889; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3KrhhtcRlCv1ET9UZpuz8xBj8pBzvf6MU5BkljWdDOQ=; b=nB07bYSxRZb32bUxdFdGWIOZIgwPErcZ/SY33eW5onZDp5+QY+U5cN0ZmQ3gZDLtyygdMj fnOeBmnwAlJbu3aDZ0nJ73xrq19/N0/vsO8uWkixXSaLFbQoj58nsAa5kX129v3xhU/NTt h2An3/o07kwtDRCG4M9JGQHkmy9MnDywQIcUTiIHD7QpRLunkonTlV2DBP8oPtM3IzRAtA 6ZGa3enTL1I7NzwZpkGgjv1uBEzae8bqaDg4/c1294VnwcZsP4MZkRq4wTpUf175Uu/++N bHgCm1Drqa9i9k8dVmKd0pxCdi4o7Fz4++tzykeHXeAS4QsAtayYyV+eAHfMlA== From: Thomas Richard Date: Tue, 06 May 2025 17:21:25 +0200 Subject: [PATCH v5 07/12] gpio: aggregator: update gpiochip_fwd_setup_delay_line() parameters 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: <20250506-aaeon-up-board-pinctrl-support-v5-7-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Remove useless parameters of gpiochip_fwd_setup_delay_line(). Reviewed-by: Andy Shevchenko Signed-off-by: Thomas Richard Reviewed-by: Geert Uytterhoeven --- drivers/gpio/gpio-aggregator.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 569c7e8ea4c2..45d713e7a702 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -476,10 +476,11 @@ static int gpiochip_fwd_delay_of_xlate(struct gpio_ch= ip *chip, return line; } =20 -static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_c= hip *chip, - struct gpiochip_fwd *fwd) +static int gpiochip_fwd_setup_delay_line(struct gpiochip_fwd *fwd) { - fwd->delay_timings =3D devm_kcalloc(dev, chip->ngpio, + struct gpio_chip *chip =3D &fwd->chip; + + fwd->delay_timings =3D devm_kcalloc(chip->parent, chip->ngpio, sizeof(*fwd->delay_timings), GFP_KERNEL); if (!fwd->delay_timings) @@ -491,8 +492,7 @@ static int gpiochip_fwd_setup_delay_line(struct device = *dev, struct gpio_chip *c return 0; } #else -static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_c= hip *chip, - struct gpiochip_fwd *fwd) +static int gpiochip_fwd_setup_delay_line(struct gpiochip_fwd *fwd) { return 0; } @@ -595,7 +595,6 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct = device *dev, unsigned long features) { struct gpiochip_fwd *fwd; - struct gpio_chip *chip; unsigned int i; int error; =20 @@ -603,8 +602,6 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct = device *dev, if (!fwd) return ERR_PTR(-ENOMEM); =20 - chip =3D &fwd->chip; - for (i =3D 0; i < ngpios; i++) { error =3D gpiochip_fwd_gpio_add(fwd, descs[i], i); if (error) @@ -612,7 +609,7 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct = device *dev, } =20 if (features & FWD_FEATURE_DELAY) { - error =3D gpiochip_fwd_setup_delay_line(dev, chip, fwd); + error =3D gpiochip_fwd_setup_delay_line(fwd); if (error) return ERR_PTR(error); } --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C91E284665; Tue, 6 May 2025 15:21:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544900; cv=none; b=uj+HyS4sTYzTEUK/iClL801T2xOCYekAYG+TSC3+WxZYp7syEBKjKJhcwEFFliawaBOKuSjiJIS0JEdjiD36RvXkmiUf5c0qp0lkqMLFAxwp1UUnOtdxY+NPneL+xmx1jRilgAlDtidF0oTaN6eWf5i7YIre9sePeiimtEiOA98= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544900; c=relaxed/simple; bh=VodF6HnjI5S4E/uVVvSj+LdRrABgzb51MDylzCMgdgU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gdpqUddLT1cmNtXs183NVDrbDwjsKv1UAtV0mFgf/zlHTnUbqEWhEw31dfELfq3WR++kguDBpnAgab+y7BrVswS61jqwlzcrtce0WDBnlhIWIxJn0uc8Kbw8OxoocjCQ9MsBwCcl7gJuaaMCqtzl2gn0GqV7wdxjFrJdflAJUH0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=SvMsx0iC; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="SvMsx0iC" Received: by mail.gandi.net (Postfix) with ESMTPSA id 8195943B45; Tue, 6 May 2025 15:21:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544890; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1Yz5xUSbZe8j9nzW7EEH2cGG2YL17cZzbuo4fldYNTQ=; b=SvMsx0iCDPUi2Z6tpI8GB1Bt12SxuBEvwcIFbOkHW04ukvc/BJqnxw8s9I4qAF6LsJyYwR ZwWvbKPcrBJO3CPAuH5F/KK2FTheqfP9HE2Z3xvtYDXQT8b9hdanF6Xpq4xu9yjbmpO2Nq KXqsUbI4fzwH6iXKu4/1bx3cm12vB18cAf99A0orgpcXzpVI21ANNhHINNUFg4vlALKdD3 r0Q7dPf51sO7epZFAZRSqu+MkYkM5p7+M4eu/G56gfCgYX6gHdhe4bTFnH2XB9qj7epEsl crgdML18nZSh6rdGobQSxnENTie1UuqYJ7D4n/9i1r3eKmJMVBdVAj9y2GG4xg== From: Thomas Richard Date: Tue, 06 May 2025 17:21:26 +0200 Subject: [PATCH v5 08/12] gpio: aggregator: export symbols of the GPIO forwarder library 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: <20250506-aaeon-up-board-pinctrl-support-v5-8-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Export all symbols and create header file for the GPIO forwarder library. It will be used in the next changes. Signed-off-by: Thomas Richard --- drivers/gpio/gpio-aggregator.c | 190 +++++++++++++++++++++++++++++++++----= ---- include/linux/gpio/forwarder.h | 42 +++++++++ 2 files changed, 197 insertions(+), 35 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 45d713e7a702..79fd44c2ceac 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -25,6 +25,7 @@ =20 #include #include +#include #include =20 #define AGGREGATOR_MAX_GPIOS 512 @@ -275,35 +276,81 @@ struct gpiochip_fwd { =20 #define fwd_tmp_size(ngpios) (BITS_TO_LONGS((ngpios)) + (ngpios)) =20 -static int gpio_fwd_get_direction(struct gpio_chip *chip, unsigned int off= set) +/** + * gpio_fwd_get_gpiochip - Get the GPIO chip for the GPIO forwarder + * @fwd: GPIO forwarder + * + * Returns: The GPIO chip for the GPIO forwarder + */ +struct gpio_chip *gpio_fwd_get_gpiochip(struct gpiochip_fwd *fwd) +{ + return &fwd->chip; +} +EXPORT_SYMBOL_NS_GPL(gpio_fwd_get_gpiochip, "GPIO_FORWARDER"); + +/** + * gpio_fwd_get_direction - Return the current direction of a GPIO forward= er line + * @chip: GPIO chip in the forwarder + * @offset: the offset of the line + * + * Returns: 0 for output, 1 for input, or an error code in case of error. + */ +int gpio_fwd_get_direction(struct gpio_chip *chip, unsigned int offset) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); =20 return gpiod_get_direction(fwd->descs[offset]); } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_get_direction, "GPIO_FORWARDER"); =20 -static int gpio_fwd_direction_input(struct gpio_chip *chip, unsigned int o= ffset) +/** + * gpio_fwd_direction_input - Set a GPIO forwarder line direction to input + * @chip: GPIO chip in the forwarder + * @offset: the offset of the line + * + * Returns: 0 on success, or negative errno on failure. + */ +int gpio_fwd_direction_input(struct gpio_chip *chip, unsigned int offset) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); =20 return gpiod_direction_input(fwd->descs[offset]); } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_direction_input, "GPIO_FORWARDER"); =20 -static int gpio_fwd_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) +/** + * gpio_fwd_direction_output - Set a GPIO forwarder line direction to outp= ut + * @chip: GPIO chip in the forwarder + * @offset: the offset of the line + * @value: value to set + * + * Returns: 0 on success, or negative errno on failure. + */ +int gpio_fwd_direction_output(struct gpio_chip *chip, unsigned int offset, + int value) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); =20 return gpiod_direction_output(fwd->descs[offset], value); } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_direction_output, "GPIO_FORWARDER"); =20 -static int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset) +/** + * gpio_fwd_get - Return a GPIO forwarder line's value + * @chip: GPIO chip in the forwarder + * @offset: the offset of the line + * + * Returns: The GPIO's logical value, i.e. taking the ACTIVE_LOW status in= to + * account, or negative errno on failure. + */ +int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); =20 return chip->can_sleep ? gpiod_get_value_cansleep(fwd->descs[offset]) : gpiod_get_value(fwd->descs[offset]); } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_get, "GPIO_FORWARDER"); =20 static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *= mask, unsigned long *bits) @@ -331,8 +378,18 @@ static int gpio_fwd_get_multiple(struct gpiochip_fwd *= fwd, unsigned long *mask, return 0; } =20 -static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) +/** + * gpio_fwd_get_multiple_locked - Get values for multiple GPIO forwarder l= ines + * @chip: GPIO chip in the forwarder + * @mask: bit mask array; one bit per line; BITS_PER_LONG bits per word de= fines + * which lines are to be read + * @bits: bit value array; one bit per line; BITS_PER_LONG bits per word w= ill + * contains the read values for the lines specified by mask + * + * Returns: 0 on success, or negative errno on failure. + */ +int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, unsigned long *ma= sk, + unsigned long *bits) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); unsigned long flags; @@ -350,6 +407,7 @@ static int gpio_fwd_get_multiple_locked(struct gpio_chi= p *chip, =20 return error; } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_get_multiple_locked, "GPIO_FORWARDER"); =20 static void gpio_fwd_delay(struct gpio_chip *chip, unsigned int offset, in= t value) { @@ -372,7 +430,15 @@ static void gpio_fwd_delay(struct gpio_chip *chip, uns= igned int offset, int valu udelay(delay_us); } =20 -static int gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int v= alue) +/** + * gpio_fwd_set - Assign value to a GPIO forwarder line. + * @chip: GPIO chip in the forwarder + * @offset: the offset of the line + * @value: value to set + * + * Returns: 0 on success, or negative errno on failure. + */ +int gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); int ret; @@ -389,6 +455,7 @@ static int gpio_fwd_set(struct gpio_chip *chip, unsigne= d int offset, int value) =20 return ret; } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_set, "GPIO_FORWARDER"); =20 static int gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *= mask, unsigned long *bits) @@ -410,8 +477,18 @@ static int gpio_fwd_set_multiple(struct gpiochip_fwd *= fwd, unsigned long *mask, return ret; } =20 -static int gpio_fwd_set_multiple_locked(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) +/** + * gpio_fwd_set_multiple_locked - Assign values to multiple GPIO forwarder= lines + * @chip: GPIO chip in the forwarder + * @mask: bit mask array; one bit per output; BITS_PER_LONG bits per word + * defines which outputs are to be changed + * @bits: bit value array; one bit per output; BITS_PER_LONG bits per word + * defines the values the outputs specified by mask are to be set to + * + * Returns: 0 on success, or negative errno on failure. + */ +int gpio_fwd_set_multiple_locked(struct gpio_chip *chip, unsigned long *ma= sk, + unsigned long *bits) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); unsigned long flags; @@ -429,21 +506,41 @@ static int gpio_fwd_set_multiple_locked(struct gpio_c= hip *chip, =20 return ret; } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_set_multiple_locked, "GPIO_FORWARDER"); =20 -static int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset, - unsigned long config) +/** + * gpio_fwd_set_config - Set @config for a GPIO forwarder line + * @chip: GPIO chip in the forwarder + * @offset: the offset of the line + * @config: Same packed config format as generic pinconf + * + * Returns: 0 on success, %-ENOTSUPP if the controller doesn't support set= ting + * the configuration. + */ +int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); =20 return gpiod_set_config(fwd->descs[offset], config); } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_set_config, "GPIO_FORWARDER"); =20 -static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) +/** + * gpio_fwd_to_irq - Return the IRQ corresponding to a GPIO forwarder line + * @chip: GPIO chip in the forwarder + * @offset: the offset of the line + * + * Returns: The IRQ corresponding to the passed line, or an error code in = case + * of error. + */ +int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); =20 return gpiod_to_irq(fwd->descs[offset]); } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_to_irq, "GPIO_FORWARDER"); =20 /* * The GPIO delay provides a way to configure platform specific delays @@ -454,9 +551,9 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsi= gned int offset) #define FWD_FEATURE_DELAY BIT(0) =20 #ifdef CONFIG_OF_GPIO -static int gpiochip_fwd_delay_of_xlate(struct gpio_chip *chip, - const struct of_phandle_args *gpiospec, - u32 *flags) +static int gpio_fwd_delay_of_xlate(struct gpio_chip *chip, + const struct of_phandle_args *gpiospec, + u32 *flags) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); struct gpiochip_fwd_timing *timings; @@ -476,7 +573,7 @@ static int gpiochip_fwd_delay_of_xlate(struct gpio_chip= *chip, return line; } =20 -static int gpiochip_fwd_setup_delay_line(struct gpiochip_fwd *fwd) +static int gpio_fwd_setup_delay_line(struct gpiochip_fwd *fwd) { struct gpio_chip *chip =3D &fwd->chip; =20 @@ -486,20 +583,27 @@ static int gpiochip_fwd_setup_delay_line(struct gpioc= hip_fwd *fwd) if (!fwd->delay_timings) return -ENOMEM; =20 - chip->of_xlate =3D gpiochip_fwd_delay_of_xlate; + chip->of_xlate =3D gpio_fwd_delay_of_xlate; chip->of_gpio_n_cells =3D 3; =20 return 0; } #else -static int gpiochip_fwd_setup_delay_line(struct gpiochip_fwd *fwd) +static int gpio_fwd_setup_delay_line(struct gpiochip_fwd *fwd) { return 0; } #endif /* !CONFIG_OF_GPIO */ =20 -static struct gpiochip_fwd * -devm_gpiochip_fwd_alloc(struct device *dev, unsigned int ngpios) +/** + * devm_gpio_fwd_alloc - Allocate and initialize a new GPIO forwarder + * @dev: Parent device pointer + * @ngpios: Number of GPIOs in the forwarder + * + * Returns: An opaque object pointer, or an ERR_PTR()-encoded negative err= or + * code on failure. + */ +struct gpiochip_fwd *devm_gpio_fwd_alloc(struct device *dev, unsigned int = ngpios) { const char *label =3D dev_name(dev); struct gpiochip_fwd *fwd; @@ -531,10 +635,18 @@ devm_gpiochip_fwd_alloc(struct device *dev, unsigned = int ngpios) =20 return fwd; } +EXPORT_SYMBOL_NS_GPL(devm_gpio_fwd_alloc, "GPIO_FORWARDER"); =20 -static int gpiochip_fwd_gpio_add(struct gpiochip_fwd *fwd, - struct gpio_desc *desc, - unsigned int offset) +/** + * gpio_fwd_gpio_add - Add a GPIO in the forwader + * @fwd: GPIO forwarder + * @desc: GPIO decriptor to register + * @offset: offset for the GPIO in the forwarder + * + * Returns: 0 on success, or negative errno on failure. + */ +int gpio_fwd_gpio_add(struct gpiochip_fwd *fwd, struct gpio_desc *desc, + unsigned int offset) { struct gpio_chip *parent =3D gpiod_to_chip(desc); struct gpio_chip *chip =3D &fwd->chip; @@ -561,8 +673,15 @@ static int gpiochip_fwd_gpio_add(struct gpiochip_fwd *= fwd, =20 return 0; } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_gpio_add, "GPIO_FORWARDER"); =20 -static int gpiochip_fwd_register(struct gpiochip_fwd *fwd) +/** + * gpio_fwd_register - Register a GPIO forwarder + * @fwd: GPIO forwarder + * + * Returns: 0 on success, or negative errno on failure. + */ +int gpio_fwd_register(struct gpiochip_fwd *fwd) { struct gpio_chip *chip =3D &fwd->chip; =20 @@ -573,9 +692,10 @@ static int gpiochip_fwd_register(struct gpiochip_fwd *= fwd) =20 return devm_gpiochip_add_data(chip->parent, chip, fwd); } +EXPORT_SYMBOL_NS_GPL(gpio_fwd_register, "GPIO_FORWARDER"); =20 /** - * gpiochip_fwd_create() - Create a new GPIO forwarder + * gpio_fwd_create() - Create a new GPIO forwarder * @dev: Parent device pointer * @ngpios: Number of GPIOs in the forwarder. * @descs: Array containing the GPIO descriptors to forward to. @@ -589,32 +709,32 @@ static int gpiochip_fwd_register(struct gpiochip_fwd = *fwd) * Return: An opaque object pointer, or an ERR_PTR()-encoded negative error * code on failure. */ -static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, - unsigned int ngpios, - struct gpio_desc *descs[], - unsigned long features) +static struct gpiochip_fwd *gpio_fwd_create(struct device *dev, + unsigned int ngpios, + struct gpio_desc *descs[], + unsigned long features) { struct gpiochip_fwd *fwd; unsigned int i; int error; =20 - fwd =3D devm_gpiochip_fwd_alloc(dev, ngpios); + fwd =3D devm_gpio_fwd_alloc(dev, ngpios); if (!fwd) return ERR_PTR(-ENOMEM); =20 for (i =3D 0; i < ngpios; i++) { - error =3D gpiochip_fwd_gpio_add(fwd, descs[i], i); + error =3D gpio_fwd_gpio_add(fwd, descs[i], i); if (error) return ERR_PTR(error); } =20 if (features & FWD_FEATURE_DELAY) { - error =3D gpiochip_fwd_setup_delay_line(fwd); + error =3D gpio_fwd_setup_delay_line(fwd); if (error) return ERR_PTR(error); } =20 - error =3D gpiochip_fwd_register(fwd); + error =3D gpio_fwd_register(fwd); if (error) return ERR_PTR(error); =20 @@ -649,7 +769,7 @@ static int gpio_aggregator_probe(struct platform_device= *pdev) } =20 features =3D (uintptr_t)device_get_match_data(dev); - fwd =3D gpiochip_fwd_create(dev, n, descs, features); + fwd =3D gpio_fwd_create(dev, n, descs, features); if (IS_ERR(fwd)) return PTR_ERR(fwd); =20 diff --git a/include/linux/gpio/forwarder.h b/include/linux/gpio/forwarder.h new file mode 100644 index 000000000000..b17ad2c8e031 --- /dev/null +++ b/include/linux/gpio/forwarder.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_GPIO_FORWARDER_H +#define __LINUX_GPIO_FORWARDER_H + +#include +#include + +struct gpiochip_fwd; + +struct gpio_chip *gpio_fwd_get_gpiochip(struct gpiochip_fwd *fwd); + +int gpio_fwd_get_direction(struct gpio_chip *chip, unsigned int offset); + +int gpio_fwd_direction_input(struct gpio_chip *chip, unsigned int offset); + +int gpio_fwd_direction_output(struct gpio_chip *chip, unsigned int offset, + int value); + +int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset); + +int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, unsigned long *ma= sk, + unsigned long *bits); + +int gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value); + +int gpio_fwd_set_multiple_locked(struct gpio_chip *chip, unsigned long *ma= sk, + unsigned long *bits); + +int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config); + +int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset); + +struct gpiochip_fwd *devm_gpio_fwd_alloc(struct device *dev, + unsigned int ngpios); + +int gpio_fwd_gpio_add(struct gpiochip_fwd *fwd, + struct gpio_desc *desc, unsigned int offset); + +int gpio_fwd_register(struct gpiochip_fwd *fwd); + +#endif --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F06622A4F0; Tue, 6 May 2025 15:21:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544895; cv=none; b=mLpNQQEYmcf5ZQMcbOkELChSyQgoa1qDOa7OuiPq/Mzi/6rBFjQlxfqcrpq1HT6foSBK5leaaoP70WvJpytJIQCy34l8sKVS6+awci2IEgLc9KHDmBh6+XghfjkOR4A7+W+D9DDkRt0OttcF7NDkdlQh5wBT9b13VbwuLsHif5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544895; c=relaxed/simple; bh=S2EEdVZOoePzaH7MtcuLAmg39V5C9k7NS6rzzXbNtMk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=o/+SV3+6DgubITInyG1b3mYZYWvCJRa5DZpXrgC5TqLfNeHrccnOh1fjIGbg31ujlH7JaMbqsS2dHFkx/kXvsRLT4/rGgMmcS1/h1VO+/uzkKhK89kUnvU7vv2Kr8uK2QG5thjBp2F1gSf+Jm7IWJ//pXtVo3YEGcpvQk3WogvI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=g8mWBFnu; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="g8mWBFnu" Received: by mail.gandi.net (Postfix) with ESMTPSA id 1551543B42; Tue, 6 May 2025 15:21:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544890; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cn2I5YeF0IITjufg1g6ZWoqrwhd3Mok5VANAi6J/Seo=; b=g8mWBFnuIFqVM355zL2tA+sEx4BmpKXSDlaB81+CkY40AdvmsPmHnT16MiKOxRrePSniCF FkQPqTm8FS4WLfw1d9p+sxqJ72tYz0Coh/vu7ny968Sc8jP42PjQiBvKV70PEkXxIGwQfO CdQwBxuM8n12XSPFTvvRrPV9bn7+SzL7lxFsCZ2rjG3Eim71lh1dTvxt2qlJOgEC1BbRk5 dUSsEdLiyAowQVjMovtUC0cB2HuF96wsCgIwRavmiVsb3uFd4cNwggbIAUw7R+EaBsV+Iq rxwlheY1tsYJPGhVU8n4wHL590RhXDTc8uDSOfVvZ7yfwwePLt3USKUrfYDCzQ== From: Thomas Richard Date: Tue, 06 May 2025 17:21:27 +0200 Subject: [PATCH v5 09/12] gpio: aggregator: handle runtime registration of gpio_desc in gpiochip_fwd 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: <20250506-aaeon-up-board-pinctrl-support-v5-9-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Add request() callback to check if the GPIO descriptor was well registered in the gpiochip_fwd before using it. This is done to handle the case where GPIO descriptor is added at runtime in the forwarder. If at least one GPIO descriptor was not added before the forwarder registration, we assume the forwarder can sleep as if a GPIO is added at runtime it may sleep. Signed-off-by: Thomas Richard --- drivers/gpio/gpio-aggregator.c | 56 +++++++++++++++++++++++++++++++++++++-= ---- include/linux/gpio/forwarder.h | 4 +++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 79fd44c2ceac..234f2f55c306 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -268,6 +268,7 @@ struct gpiochip_fwd { spinlock_t slock; /* protects tmp[] if !can_sleep */ }; struct gpiochip_fwd_timing *delay_timings; + unsigned long *valid_mask; unsigned long tmp[]; /* values and descs for multiple ops */ }; =20 @@ -288,6 +289,21 @@ struct gpio_chip *gpio_fwd_get_gpiochip(struct gpiochi= p_fwd *fwd) } EXPORT_SYMBOL_NS_GPL(gpio_fwd_get_gpiochip, "GPIO_FORWARDER"); =20 +/** + * gpio_fwd_request - Request a line of the GPIO forwarder + * @chip: GPIO chip in the forwarder + * @offset: the offset of the line to request + * + * Returns: 0 on success, or negative errno on failure. + */ +int gpio_fwd_request(struct gpio_chip *chip, unsigned int offset) +{ + struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); + + return test_bit(offset, fwd->valid_mask) ? 0 : -ENODEV; +} +EXPORT_SYMBOL_NS_GPL(gpio_fwd_request, "GPIO_FORWARDER"); + /** * gpio_fwd_get_direction - Return the current direction of a GPIO forward= er line * @chip: GPIO chip in the forwarder @@ -299,6 +315,13 @@ int gpio_fwd_get_direction(struct gpio_chip *chip, uns= igned int offset) { struct gpiochip_fwd *fwd =3D gpiochip_get_data(chip); =20 + /* + * get_direction() is called during gpiochip registration, return input + * direction if there is no descriptor for the line. + */ + if (!test_bit(offset, fwd->valid_mask)) + return GPIO_LINE_DIRECTION_IN; + return gpiod_get_direction(fwd->descs[offset]); } EXPORT_SYMBOL_NS_GPL(gpio_fwd_get_direction, "GPIO_FORWARDER"); @@ -617,11 +640,16 @@ struct gpiochip_fwd *devm_gpio_fwd_alloc(struct devic= e *dev, unsigned int ngpios if (!fwd->descs) return ERR_PTR(-ENOMEM); =20 + fwd->valid_mask =3D devm_bitmap_zalloc(dev, ngpios, GFP_KERNEL); + if (!fwd->valid_mask) + return ERR_PTR(-ENOMEM); + chip =3D &fwd->chip; =20 chip->label =3D label; chip->parent =3D dev; chip->owner =3D THIS_MODULE; + chip->request =3D gpio_fwd_request; chip->get_direction =3D gpio_fwd_get_direction; chip->direction_input =3D gpio_fwd_direction_input; chip->direction_output =3D gpio_fwd_direction_output; @@ -648,24 +676,21 @@ EXPORT_SYMBOL_NS_GPL(devm_gpio_fwd_alloc, "GPIO_FORWA= RDER"); int gpio_fwd_gpio_add(struct gpiochip_fwd *fwd, struct gpio_desc *desc, unsigned int offset) { - struct gpio_chip *parent =3D gpiod_to_chip(desc); struct gpio_chip *chip =3D &fwd->chip; =20 if (offset > chip->ngpio) return -EINVAL; =20 + if (test_and_set_bit(offset, fwd->valid_mask)) + return -EEXIST; + /* * If any of the GPIO lines are sleeping, then the entire forwarder * will be sleeping. - * If any of the chips support .set_config(), then the forwarder will - * support setting configs. */ if (gpiod_cansleep(desc)) chip->can_sleep =3D true; =20 - if (parent && parent->set_config) - chip->set_config =3D gpio_fwd_set_config; - fwd->descs[offset] =3D desc; =20 dev_dbg(chip->parent, "%u =3D> gpio %d irq %d\n", offset, @@ -675,6 +700,18 @@ int gpio_fwd_gpio_add(struct gpiochip_fwd *fwd, struct= gpio_desc *desc, } EXPORT_SYMBOL_NS_GPL(gpio_fwd_gpio_add, "GPIO_FORWARDER"); =20 +/** + * gpio_fwd_gpio_free - Remove a GPIO from the forwarder + * @fwd: GPIO forwarder + * @offset: offset of GPIO to remove + */ +void gpio_fwd_gpio_free(struct gpiochip_fwd *fwd, unsigned int offset) +{ + if (test_and_clear_bit(offset, fwd->valid_mask)) + gpiod_put(fwd->descs[offset]); +} +EXPORT_SYMBOL_NS_GPL(gpio_fwd_gpio_free, "GPIO_FORWARDER"); + /** * gpio_fwd_register - Register a GPIO forwarder * @fwd: GPIO forwarder @@ -685,6 +722,13 @@ int gpio_fwd_register(struct gpiochip_fwd *fwd) { struct gpio_chip *chip =3D &fwd->chip; =20 + /* + * Some gpio_desc were not registered. They will be registered at runtime + * but we have to suppose they can sleep. + */ + if (!bitmap_full(fwd->valid_mask, chip->ngpio)) + chip->can_sleep =3D true; + if (chip->can_sleep) mutex_init(&fwd->mlock); else diff --git a/include/linux/gpio/forwarder.h b/include/linux/gpio/forwarder.h index b17ad2c8e031..f799b0377efd 100644 --- a/include/linux/gpio/forwarder.h +++ b/include/linux/gpio/forwarder.h @@ -9,6 +9,8 @@ struct gpiochip_fwd; =20 struct gpio_chip *gpio_fwd_get_gpiochip(struct gpiochip_fwd *fwd); =20 +int gpio_fwd_request(struct gpio_chip *chip, unsigned int offset); + int gpio_fwd_get_direction(struct gpio_chip *chip, unsigned int offset); =20 int gpio_fwd_direction_input(struct gpio_chip *chip, unsigned int offset); @@ -37,6 +39,8 @@ struct gpiochip_fwd *devm_gpio_fwd_alloc(struct device *d= ev, int gpio_fwd_gpio_add(struct gpiochip_fwd *fwd, struct gpio_desc *desc, unsigned int offset); =20 +void gpio_fwd_gpio_free(struct gpiochip_fwd *fwd, unsigned int offset); + int gpio_fwd_register(struct gpiochip_fwd *fwd); =20 #endif --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B3AB9283FED; Tue, 6 May 2025 15:21:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544899; cv=none; b=JN/tp8CRso+AhbXWpwEZ4Czmc9DoGSyOMFejR0dBACgPXZ145Zk1MoisQAT7ABuKY5wKMrIt5XQbnu6G4V94Lhx3dfQI/MIlSydUoxfm0w3fkOa8nmI8cwUeSW8TMi9FUUo7bMyHhD153OIg5ZbWl2vxUqW4mgFF8FnQklRvxqk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544899; c=relaxed/simple; bh=8ZojBhH8SC9IQKM+gRCef0n5m7k3csgRxWFhEmByAgU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DHarFE2Ta1OxjfUwfcD4wIgpvAGOkN+oCK9DpQicZyeJuHh8c0VRt8v73wIpUcWnS1pnmRo+/ZDudH+lVAZPdMgPE7qQiVmVzMLBN7hk63puZgVfQcxZwLQjXduKdSWFeTDRosyEu1ffoVbzRhX8zQujM700QtJLCTQ4UcY/oGw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=NgxL0LL5; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="NgxL0LL5" Received: by mail.gandi.net (Postfix) with ESMTPSA id A064C43B43; Tue, 6 May 2025 15:21:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544891; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3RrTt6YOR2RDmIgOFmK3Bea23zIK1IY+chIFKWyua1g=; b=NgxL0LL5wV46uQS/XEdXoxLvUaLRPYZsJ3B7caSBpYRT3bmuF7cq1wzNQDYuuFt0wJm4WJ 2eNThtdyOT+ZrKQtrM+zmJLXBEryMI1kwL5TDrMcAI0h+DxSYJ5lXvpCr+9yVreSPhEZhn tnW1yheebyKJXRdUGRfB+pMzK3UCOTPkY0ql1WFKueAKrHkfbIZv0tmkjoRzXomTnlm3MG TdTuBsqEXCi1q9O79eefaxtUelkcbD71kVnGuLe0DR6eMx5YXWT4DoEhr7u/KQgKyJNLSv HXSLxpBoORmutoIPyEt7W4r/nmifAWdhvEbEFm0+AwaTJZiLjd3U9abZYkpF8Q== From: Thomas Richard Date: Tue, 06 May 2025 17:21:28 +0200 Subject: [PATCH v5 10/12] gpio: aggregator: add possibility to attach data to the forwarder 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: <20250506-aaeon-up-board-pinctrl-support-v5-10-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Add a data pointer to store private data in the forwarder. Reviewed-by: Andy Shevchenko Signed-off-by: Thomas Richard Reviewed-by: Geert Uytterhoeven --- drivers/gpio/gpio-aggregator.c | 20 ++++++++++++++++++-- include/linux/gpio/forwarder.h | 4 +++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 234f2f55c306..102205793015 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -268,6 +268,7 @@ struct gpiochip_fwd { spinlock_t slock; /* protects tmp[] if !can_sleep */ }; struct gpiochip_fwd_timing *delay_timings; + void *data; unsigned long *valid_mask; unsigned long tmp[]; /* values and descs for multiple ops */ }; @@ -289,6 +290,18 @@ struct gpio_chip *gpio_fwd_get_gpiochip(struct gpiochi= p_fwd *fwd) } EXPORT_SYMBOL_NS_GPL(gpio_fwd_get_gpiochip, "GPIO_FORWARDER"); =20 +/** + * gpio_fwd_get_data - Get data for the GPIO forwarder + * @fwd: GPIO forwarder + * + * Returns: The data for the GPIO forwarder + */ +void *gpio_fwd_get_data(struct gpiochip_fwd *fwd) +{ + return fwd->data; +} +EXPORT_SYMBOL_NS_GPL(gpio_fwd_get_data, "GPIO_FORWARDER"); + /** * gpio_fwd_request - Request a line of the GPIO forwarder * @chip: GPIO chip in the forwarder @@ -715,10 +728,11 @@ EXPORT_SYMBOL_NS_GPL(gpio_fwd_gpio_free, "GPIO_FORWAR= DER"); /** * gpio_fwd_register - Register a GPIO forwarder * @fwd: GPIO forwarder + * @data: driver-private data associated with this forwarder * * Returns: 0 on success, or negative errno on failure. */ -int gpio_fwd_register(struct gpiochip_fwd *fwd) +int gpio_fwd_register(struct gpiochip_fwd *fwd, void *data) { struct gpio_chip *chip =3D &fwd->chip; =20 @@ -734,6 +748,8 @@ int gpio_fwd_register(struct gpiochip_fwd *fwd) else spin_lock_init(&fwd->slock); =20 + fwd->data =3D data; + return devm_gpiochip_add_data(chip->parent, chip, fwd); } EXPORT_SYMBOL_NS_GPL(gpio_fwd_register, "GPIO_FORWARDER"); @@ -778,7 +794,7 @@ static struct gpiochip_fwd *gpio_fwd_create(struct devi= ce *dev, return ERR_PTR(error); } =20 - error =3D gpio_fwd_register(fwd); + error =3D gpio_fwd_register(fwd, NULL); if (error) return ERR_PTR(error); =20 diff --git a/include/linux/gpio/forwarder.h b/include/linux/gpio/forwarder.h index f799b0377efd..dc9b0f13413d 100644 --- a/include/linux/gpio/forwarder.h +++ b/include/linux/gpio/forwarder.h @@ -9,6 +9,8 @@ struct gpiochip_fwd; =20 struct gpio_chip *gpio_fwd_get_gpiochip(struct gpiochip_fwd *fwd); =20 +void *gpio_fwd_get_data(struct gpiochip_fwd *fwd); + int gpio_fwd_request(struct gpio_chip *chip, unsigned int offset); =20 int gpio_fwd_get_direction(struct gpio_chip *chip, unsigned int offset); @@ -41,6 +43,6 @@ int gpio_fwd_gpio_add(struct gpiochip_fwd *fwd, =20 void gpio_fwd_gpio_free(struct gpiochip_fwd *fwd, unsigned int offset); =20 -int gpio_fwd_register(struct gpiochip_fwd *fwd); +int gpio_fwd_register(struct gpiochip_fwd *fwd, void *data); =20 #endif --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A7B4C283FE8; Tue, 6 May 2025 15:21:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544899; cv=none; b=NJkeGcVcW3diSXLtB3NZNfsudu+T+uqf8F/TRM+aNC8qifF2rPXgMMerehBcoq4SKsJaJoCnQr9FvhdppS5T4Y2beVKdS4gBJtG+/w2HLnF76DFWEcL4A2Go1z2Rv9qeqyj5LB2PUFP6P4fcFd62Pj64EUifRHa7pRGID5vvq5c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544899; c=relaxed/simple; bh=c/VjgngVldLlTaqu+7JoDMmHcqtvz8kBdxTEdrJXtao=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=swlinQzHTm2mu3q/LZg3HvMmTq2u5HNaz7WEYYtZyltuK9bY3OGAO597fIFy5TY/JOW//Ms+Sqe9KmfhiGy+fVhI7v5iXPI4dXYJIyQU3BF+ExUPSF9UA98PTC8RXh6KIegcfXurD6NgAz4jIrDSmPh+3/72bsozK20FvoHhRwk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=YAPFuodd; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="YAPFuodd" Received: by mail.gandi.net (Postfix) with ESMTPSA id 37EE6433F6; Tue, 6 May 2025 15:21:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544891; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8+O5hiCoC5alHeoniheaAHRlGSS5BBU+n2qDYbHK6bQ=; b=YAPFuoddlkbXsIPfeWeEilcFsuMsPNOdQ/1ftgT6Oabh3EOK3SqnU06ll94uh7nMOZq3t5 zrB0izfFa/+tsyS9Fb6ssaZQTz2MtpOapeLngQKwXCjp03vQYOfktPejg6nq0rBpAozlyD 0zorhyU71FyyJbQ0cad/AwLEPb1qGmxxdDiadJApI9mIZyv+EjQRIxfX4jqCQiXxV8/ZFd p/zvwMNzUFzeFuZgZm5v6si3spTnxYayUWprVvIhnIBj6mh2Q1iKRP9RG5eoH5bKo3oUNd mN2npZ4oyAUNOaXT9vi/BXUQ1QZ+bb45vPSNATgjK93v435eQzy9SZnwEtXTLg== From: Thomas Richard Date: Tue, 06 May 2025 17:21:29 +0200 Subject: [PATCH v5 11/12] lib/string_choices: Add str_input_output() helper 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: <20250506-aaeon-up-board-pinctrl-support-v5-11-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com Add str_input_output() helper to return 'input' or 'output' string literal. Also add the inversed variant str_output_input(). Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Thomas Richard --- include/linux/string_choices.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/string_choices.h b/include/linux/string_choices.h index f3ba4f52ff26..a27c87c954ae 100644 --- a/include/linux/string_choices.h +++ b/include/linux/string_choices.h @@ -41,6 +41,12 @@ static inline const char *str_high_low(bool v) } #define str_low_high(v) str_high_low(!(v)) =20 +static inline const char *str_input_output(bool v) +{ + return v ? "input" : "output"; +} +#define str_output_input(v) str_input_output(!(v)) + static inline const char *str_on_off(bool v) { return v ? "on" : "off"; --=20 2.39.5 From nobody Tue Dec 16 15:45:37 2025 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68A1C28466C; Tue, 6 May 2025 15:21:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544901; cv=none; b=RJDpPgc1M1uDeTU26EEf6NZHyn5JXgmaI2O/q0SsVa+6bWOzD7/clRSfTZCmdFeqmBc2Bn6ZEvxiEhDVCJXb8QpB6OsmUOaOxbxwEye2ldcM3ZZumYfSB9gv1xuJGerDerc42Eh8MceJzj400ZSqEFaafjhPFNoUXvEm/1oDbsc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746544901; c=relaxed/simple; bh=K5QU9y+yPtehN4sePIECrsV3DEzKvAZa4KzxhaFERU4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ehaTyWBbnKnzKvnEfNbDMMn7apmcu5zj3WJvwDXBC3fFH7xTdguPVMdA0eO9QVr+YtR0VZCMRI1Z3ihFQT470yankmvIT2wXCo40VILd89uvzvO56PU7HxoC5Q+0ckrsKMKLfxu14g5PH08eTCrgcmoz5HOP1rwQxUbhXGmXbGY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=fyz7tCxA; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="fyz7tCxA" Received: by mail.gandi.net (Postfix) with ESMTPSA id BAF4843B35; Tue, 6 May 2025 15:21:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1746544892; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WzjIAjC0nquXUziVgdl+8qNv1S11/idNhy5z2YetIIk=; b=fyz7tCxAQpAedGq/8XlDwfE139TItpV4Rj/co9HtTf2MxPE/RVY4cxjHq/BHIOZ3pi4wXT fVHmYz8gKxLyJr7LC5VeDzXF74u5m89YBf0h5S/FoFWQ5KEpWV5lEr+DPIMPYem8GlbJlG 4Z2Gtb5ltT8V81plvy37xvbu+QsQH9LNT7vu4G0ZuHrL37EygWia+0JersEIEY9uHXznRG fZXOaCo7+gmz6Qxo42u0J9cV7VS4d/dga/d+FVDAE4C5HkEzsOPjUd3eEp1hd1VTzMZk9S HHuYtjnyhDANdr9taN7xBtsmqMTacIrMH900VDX5W8AERWZK9lL1ju7ecFxsug== From: Thomas Richard Date: Tue, 06 May 2025 17:21:30 +0200 Subject: [PATCH v5 12/12] pinctrl: Add pin controller driver for AAEON UP boards 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: <20250506-aaeon-up-board-pinctrl-support-v5-12-3906529757d2@bootlin.com> References: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> In-Reply-To: <20250506-aaeon-up-board-pinctrl-support-v5-0-3906529757d2@bootlin.com> To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski , Geert Uytterhoeven , Kees Cook , Andy Shevchenko Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, DanieleCleri@aaeon.eu, GaryWang@aaeon.com.tw, linux-hardening@vger.kernel.org, Thomas Richard X-Mailer: b4 0.14.1 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeegfeefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuifetpfffkfdpucggtfgfnhhsuhgsshgtrhhisggvnecuuegrihhlohhuthemuceftddunecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhfffugggtgffkfhgjvfevofesthejredtredtjeenucfhrhhomhepvfhhohhmrghsucftihgthhgrrhguuceothhhohhmrghsrdhrihgthhgrrhgusegsohhothhlihhnrdgtohhmqeenucggtffrrghtthgvrhhnpeektdehvdeiteehtdelteffheduveelgeelvdetgedvueejgefhhfekgefgfeduveenucfkphepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepvdgrtddumegtsgdugeemheehieemjegrtddtmegutgekudemrggrugdtmehfuggtrgemtggtudgrpdhhvghloheplgduvdejrddtrddurddungdpmhgrihhlfhhrohhmpehthhhomhgrshdrrhhitghhrghrugessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohepudefpdhrtghpthhtohepghgvvghrthdorhgvnhgvshgrshesghhlihguvghrrdgsvgdprhgtphhtthhopegsrhhglhessghguggvvhdrphhlpdhrtghpthhtohepkhgvvghssehkvghrnhgvlhdrohhrghdprhgtphhtthhopegrnhgurhhihidrshhhvghvt ghhvghnkhhosehlihhnuhigrdhinhhtvghlrdgtohhmpdhrtghpthhtoheplhhinhhushdrfigrlhhlvghijheslhhinhgrrhhordhorhhgpdhrtghpthhtoheplhhinhhugidqghhpihhosehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepthhhohhmrghsrdhpvghtrgiiiihonhhisegsohhothhlihhnrdgtohhm X-GND-Sasl: thomas.richard@bootlin.com This enables the pin control support of the onboard FPGA on AAEON UP boards. This FPGA acts as a level shifter between the Intel SoC pins and the pin header, and also as a mux or switch. +---------+ +--------------+ +---+ | | | | | | PWM0 | \ | | H | |----------|------ \-----|-------------| E | | I2C0_SDA | | | A | Intel SoC |----------|------\ | | D | | GPIO0 | \------|-------------| E | |----------|------ | | R | | | FPGA | | | Reviewed-by: Linus Walleij ----------+ +--------------+ +---+ For most of the pins, the FPGA opens/closes a switch to enable/disable the access to the SoC pin from a pin header. Each switch, has a direction flag that is set depending the status of the SoC pin. For some other pins, the FPGA acts as a mux, and routes one pin (or the other one) to the header. The driver also provides a GPIO chip. It requests SoC pins in GPIO mode, and drives them in tandem with FPGA pins (switch/mux direction). This commit adds support only for UP Squared board. Reviewed-by: Linus Walleij Signed-off-by: Thomas Richard --- drivers/pinctrl/Kconfig | 19 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-upboard.c | 1068 +++++++++++++++++++++++++++++++++= ++++ 3 files changed, 1088 insertions(+) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 464cc9aca157..b19eff31146b 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -590,6 +590,25 @@ config PINCTRL_TH1520 This driver is needed for RISC-V development boards like the BeagleV Ahead and the LicheePi 4A. =20 +config PINCTRL_UPBOARD + tristate "AAeon UP board FPGA pin controller" + depends on MFD_UPBOARD_FPGA + select PINMUX + select GENERIC_PINCTRL_GROUPS + select GENERIC_PINMUX_FUNCTIONS + select GPIOLIB + select GPIO_AGGREGATOR + help + Pin controller for the FPGA GPIO lines on UP boards. Due to the + hardware layout, the driver controls the FPGA pins in tandem with + their corresponding Intel SoC GPIOs. + + Currently supported: + - UP Squared + + To compile this driver as a module, choose M here: the module + will be called pinctrl-upboard. + config PINCTRL_ZYNQ bool "Pinctrl driver for Xilinx Zynq" depends on ARCH_ZYNQ diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index ac27e88677d1..f7246aead7b5 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_PINCTRL_SX150X) +=3D pinctrl-sx150x.o obj-$(CONFIG_PINCTRL_TB10X) +=3D pinctrl-tb10x.o obj-$(CONFIG_PINCTRL_TPS6594) +=3D pinctrl-tps6594.o obj-$(CONFIG_PINCTRL_TH1520) +=3D pinctrl-th1520.o +obj-$(CONFIG_PINCTRL_UPBOARD) +=3D pinctrl-upboard.o obj-$(CONFIG_PINCTRL_ZYNQMP) +=3D pinctrl-zynqmp.o obj-$(CONFIG_PINCTRL_ZYNQ) +=3D pinctrl-zynq.o =20 diff --git a/drivers/pinctrl/pinctrl-upboard.c b/drivers/pinctrl/pinctrl-up= board.c new file mode 100644 index 000000000000..097a8dbbd472 --- /dev/null +++ b/drivers/pinctrl/pinctrl-upboard.c @@ -0,0 +1,1068 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * UP board pin control driver. + * + * Copyright (C) 2025 Bootlin + * + * Author: Thomas Richard + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "core.h" +#include "pinmux.h" + +enum upboard_board_id { + UPBOARD_APL01, +}; + +enum upboard_pin_mode { + UPBOARD_PIN_MODE_FUNCTION, + UPBOARD_PIN_MODE_GPIO_IN, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_DISABLED, +}; + +struct upboard_pin { + struct regmap_field *funcbit; + struct regmap_field *enbit; + struct regmap_field *dirbit; +}; + +struct upboard_pingroup { + struct pingroup grp; + enum upboard_pin_mode mode; + const enum upboard_pin_mode *modes; +}; + +struct upboard_pinctrl_data { + const struct upboard_pingroup *groups; + size_t ngroups; + const struct pinfunction *funcs; + size_t nfuncs; + const unsigned int *pin_header; + size_t ngpio; +}; + +struct upboard_pinctrl { + struct device *dev; + struct pinctrl_dev *pctldev; + const struct upboard_pinctrl_data *pctrl_data; + struct gpio_pin_range pin_range; + struct upboard_pin *pins; + const struct pinctrl_map *maps; + size_t nmaps; +}; + +enum upboard_func0_fpgabit { + UPBOARD_FUNC_I2C0_EN =3D 8, + UPBOARD_FUNC_I2C1_EN =3D 9, + UPBOARD_FUNC_CEC0_EN =3D 12, + UPBOARD_FUNC_ADC0_EN =3D 14, +}; + +static const struct reg_field upboard_i2c0_reg =3D + REG_FIELD(UPBOARD_REG_FUNC_EN0, UPBOARD_FUNC_I2C0_EN, UPBOARD_FUNC_I2C0_E= N); + +static const struct reg_field upboard_i2c1_reg =3D + REG_FIELD(UPBOARD_REG_FUNC_EN0, UPBOARD_FUNC_I2C1_EN, UPBOARD_FUNC_I2C1_E= N); + +static const struct reg_field upboard_adc0_reg =3D + REG_FIELD(UPBOARD_REG_FUNC_EN0, UPBOARD_FUNC_ADC0_EN, UPBOARD_FUNC_ADC0_E= N); + +#define UPBOARD_UP_BIT_TO_PIN(bit) UPBOARD_UP_BIT_##bit + +#define UPBOARD_UP_PIN_NAME(id) \ + { \ + .number =3D UPBOARD_UP_BIT_##id, \ + .name =3D #id, \ + } + +#define UPBOARD_UP_PIN_MUX(bit, data) \ + { \ + .number =3D UPBOARD_UP_BIT_##bit, \ + .name =3D "PINMUX_"#bit, \ + .drv_data =3D (void *)(data), \ + } + +#define UPBOARD_UP_PIN_FUNC(id, data) \ + { \ + .number =3D UPBOARD_UP_BIT_##id, \ + .name =3D #id, \ + .drv_data =3D (void *)(data), \ + } + +enum upboard_up_fpgabit { + UPBOARD_UP_BIT_I2C1_SDA, + UPBOARD_UP_BIT_I2C1_SCL, + UPBOARD_UP_BIT_ADC0, + UPBOARD_UP_BIT_UART1_RTS, + UPBOARD_UP_BIT_GPIO27, + UPBOARD_UP_BIT_GPIO22, + UPBOARD_UP_BIT_SPI_MOSI, + UPBOARD_UP_BIT_SPI_MISO, + UPBOARD_UP_BIT_SPI_CLK, + UPBOARD_UP_BIT_I2C0_SDA, + UPBOARD_UP_BIT_GPIO5, + UPBOARD_UP_BIT_GPIO6, + UPBOARD_UP_BIT_PWM1, + UPBOARD_UP_BIT_I2S_FRM, + UPBOARD_UP_BIT_GPIO26, + UPBOARD_UP_BIT_UART1_TX, + UPBOARD_UP_BIT_UART1_RX, + UPBOARD_UP_BIT_I2S_CLK, + UPBOARD_UP_BIT_GPIO23, + UPBOARD_UP_BIT_GPIO24, + UPBOARD_UP_BIT_GPIO25, + UPBOARD_UP_BIT_SPI_CS0, + UPBOARD_UP_BIT_SPI_CS1, + UPBOARD_UP_BIT_I2C0_SCL, + UPBOARD_UP_BIT_PWM0, + UPBOARD_UP_BIT_UART1_CTS, + UPBOARD_UP_BIT_I2S_DIN, + UPBOARD_UP_BIT_I2S_DOUT, +}; + +static const struct pinctrl_pin_desc upboard_up_pins[] =3D { + UPBOARD_UP_PIN_FUNC(I2C1_SDA, &upboard_i2c1_reg), + UPBOARD_UP_PIN_FUNC(I2C1_SCL, &upboard_i2c1_reg), + UPBOARD_UP_PIN_FUNC(ADC0, &upboard_adc0_reg), + UPBOARD_UP_PIN_NAME(UART1_RTS), + UPBOARD_UP_PIN_NAME(GPIO27), + UPBOARD_UP_PIN_NAME(GPIO22), + UPBOARD_UP_PIN_NAME(SPI_MOSI), + UPBOARD_UP_PIN_NAME(SPI_MISO), + UPBOARD_UP_PIN_NAME(SPI_CLK), + UPBOARD_UP_PIN_FUNC(I2C0_SDA, &upboard_i2c0_reg), + UPBOARD_UP_PIN_NAME(GPIO5), + UPBOARD_UP_PIN_NAME(GPIO6), + UPBOARD_UP_PIN_NAME(PWM1), + UPBOARD_UP_PIN_NAME(I2S_FRM), + UPBOARD_UP_PIN_NAME(GPIO26), + UPBOARD_UP_PIN_NAME(UART1_TX), + UPBOARD_UP_PIN_NAME(UART1_RX), + UPBOARD_UP_PIN_NAME(I2S_CLK), + UPBOARD_UP_PIN_NAME(GPIO23), + UPBOARD_UP_PIN_NAME(GPIO24), + UPBOARD_UP_PIN_NAME(GPIO25), + UPBOARD_UP_PIN_NAME(SPI_CS0), + UPBOARD_UP_PIN_NAME(SPI_CS1), + UPBOARD_UP_PIN_FUNC(I2C0_SCL, &upboard_i2c0_reg), + UPBOARD_UP_PIN_NAME(PWM0), + UPBOARD_UP_PIN_NAME(UART1_CTS), + UPBOARD_UP_PIN_NAME(I2S_DIN), + UPBOARD_UP_PIN_NAME(I2S_DOUT), +}; + +static const unsigned int upboard_up_pin_header[] =3D { + UPBOARD_UP_BIT_TO_PIN(I2C0_SDA), + UPBOARD_UP_BIT_TO_PIN(I2C0_SCL), + UPBOARD_UP_BIT_TO_PIN(I2C1_SDA), + UPBOARD_UP_BIT_TO_PIN(I2C1_SCL), + UPBOARD_UP_BIT_TO_PIN(ADC0), + UPBOARD_UP_BIT_TO_PIN(GPIO5), + UPBOARD_UP_BIT_TO_PIN(GPIO6), + UPBOARD_UP_BIT_TO_PIN(SPI_CS1), + UPBOARD_UP_BIT_TO_PIN(SPI_CS0), + UPBOARD_UP_BIT_TO_PIN(SPI_MISO), + UPBOARD_UP_BIT_TO_PIN(SPI_MOSI), + UPBOARD_UP_BIT_TO_PIN(SPI_CLK), + UPBOARD_UP_BIT_TO_PIN(PWM0), + UPBOARD_UP_BIT_TO_PIN(PWM1), + UPBOARD_UP_BIT_TO_PIN(UART1_TX), + UPBOARD_UP_BIT_TO_PIN(UART1_RX), + UPBOARD_UP_BIT_TO_PIN(UART1_CTS), + UPBOARD_UP_BIT_TO_PIN(UART1_RTS), + UPBOARD_UP_BIT_TO_PIN(I2S_CLK), + UPBOARD_UP_BIT_TO_PIN(I2S_FRM), + UPBOARD_UP_BIT_TO_PIN(I2S_DIN), + UPBOARD_UP_BIT_TO_PIN(I2S_DOUT), + UPBOARD_UP_BIT_TO_PIN(GPIO22), + UPBOARD_UP_BIT_TO_PIN(GPIO23), + UPBOARD_UP_BIT_TO_PIN(GPIO24), + UPBOARD_UP_BIT_TO_PIN(GPIO25), + UPBOARD_UP_BIT_TO_PIN(GPIO26), + UPBOARD_UP_BIT_TO_PIN(GPIO27), +}; + +static const unsigned int upboard_up_uart1_pins[] =3D { + UPBOARD_UP_BIT_TO_PIN(UART1_TX), + UPBOARD_UP_BIT_TO_PIN(UART1_RX), + UPBOARD_UP_BIT_TO_PIN(UART1_RTS), + UPBOARD_UP_BIT_TO_PIN(UART1_CTS), +}; + +static const enum upboard_pin_mode upboard_up_uart1_modes[] =3D { + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_IN, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_IN, +}; + +static_assert(ARRAY_SIZE(upboard_up_uart1_modes) =3D=3D ARRAY_SIZE(upboard= _up_uart1_pins)); + +static const unsigned int upboard_up_i2c0_pins[] =3D { + UPBOARD_UP_BIT_TO_PIN(I2C0_SCL), + UPBOARD_UP_BIT_TO_PIN(I2C0_SDA), +}; + +static const unsigned int upboard_up_i2c1_pins[] =3D { + UPBOARD_UP_BIT_TO_PIN(I2C1_SCL), + UPBOARD_UP_BIT_TO_PIN(I2C1_SDA), +}; + +static const unsigned int upboard_up_spi2_pins[] =3D { + UPBOARD_UP_BIT_TO_PIN(SPI_MOSI), + UPBOARD_UP_BIT_TO_PIN(SPI_MISO), + UPBOARD_UP_BIT_TO_PIN(SPI_CLK), + UPBOARD_UP_BIT_TO_PIN(SPI_CS0), + UPBOARD_UP_BIT_TO_PIN(SPI_CS1), +}; + +static const enum upboard_pin_mode upboard_up_spi2_modes[] =3D { + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_IN, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_OUT, +}; + +static_assert(ARRAY_SIZE(upboard_up_spi2_modes) =3D=3D ARRAY_SIZE(upboard_= up_spi2_pins)); + +static const unsigned int upboard_up_i2s0_pins[] =3D { + UPBOARD_UP_BIT_TO_PIN(I2S_FRM), + UPBOARD_UP_BIT_TO_PIN(I2S_CLK), + UPBOARD_UP_BIT_TO_PIN(I2S_DIN), + UPBOARD_UP_BIT_TO_PIN(I2S_DOUT), +}; + +static const enum upboard_pin_mode upboard_up_i2s0_modes[] =3D { + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_IN, + UPBOARD_PIN_MODE_GPIO_OUT, +}; + +static_assert(ARRAY_SIZE(upboard_up_i2s0_pins) =3D=3D ARRAY_SIZE(upboard_u= p_i2s0_modes)); + +static const unsigned int upboard_up_pwm0_pins[] =3D { + UPBOARD_UP_BIT_TO_PIN(PWM0), +}; + +static const unsigned int upboard_up_pwm1_pins[] =3D { + UPBOARD_UP_BIT_TO_PIN(PWM1), +}; + +static const unsigned int upboard_up_adc0_pins[] =3D { + UPBOARD_UP_BIT_TO_PIN(ADC0), +}; + +#define UPBOARD_PINGROUP(n, p, m) \ +{ \ + .grp =3D PINCTRL_PINGROUP(n, p, ARRAY_SIZE(p)), \ + .mode =3D __builtin_choose_expr( \ + __builtin_types_compatible_p(typeof(m), const enum upboard_pin_mode *),= \ + 0, m), \ + .modes =3D __builtin_choose_expr( \ + __builtin_types_compatible_p(typeof(m), const enum upboard_pin_mode *),= \ + m, NULL), \ +} + +static const struct upboard_pingroup upboard_up_pin_groups[] =3D { + UPBOARD_PINGROUP("uart1_grp", upboard_up_uart1_pins, &upboard_up_uart1_mo= des[0]), + UPBOARD_PINGROUP("i2c0_grp", upboard_up_i2c0_pins, UPBOARD_PIN_MODE_GPIO_= OUT), + UPBOARD_PINGROUP("i2c1_grp", upboard_up_i2c1_pins, UPBOARD_PIN_MODE_GPIO_= OUT), + UPBOARD_PINGROUP("spi2_grp", upboard_up_spi2_pins, &upboard_up_spi2_modes= [0]), + UPBOARD_PINGROUP("i2s0_grp", upboard_up_i2s0_pins, &upboard_up_i2s0_modes= [0]), + UPBOARD_PINGROUP("pwm0_grp", upboard_up_pwm0_pins, UPBOARD_PIN_MODE_GPIO_= OUT), + UPBOARD_PINGROUP("pwm1_grp", upboard_up_pwm1_pins, UPBOARD_PIN_MODE_GPIO_= OUT), + UPBOARD_PINGROUP("adc0_grp", upboard_up_adc0_pins, UPBOARD_PIN_MODE_GPIO_= IN), +}; + +static const char * const upboard_up_uart1_groups[] =3D { "uart1_grp" }; +static const char * const upboard_up_i2c0_groups[] =3D { "i2c0_grp" }; +static const char * const upboard_up_i2c1_groups[] =3D { "i2c1_grp" }; +static const char * const upboard_up_spi2_groups[] =3D { "spi2_grp" }; +static const char * const upboard_up_i2s0_groups[] =3D { "i2s0_grp" }; +static const char * const upboard_up_pwm0_groups[] =3D { "pwm0_grp" }; +static const char * const upboard_up_pwm1_groups[] =3D { "pwm1_grp" }; +static const char * const upboard_up_adc0_groups[] =3D { "adc0_grp" }; + +#define UPBOARD_FUNCTION(func, groups) PINCTRL_PINFUNCTION(func, groups, A= RRAY_SIZE(groups)) + +static const struct pinfunction upboard_up_pin_functions[] =3D { + UPBOARD_FUNCTION("uart1", upboard_up_uart1_groups), + UPBOARD_FUNCTION("i2c0", upboard_up_i2c0_groups), + UPBOARD_FUNCTION("i2c1", upboard_up_i2c1_groups), + UPBOARD_FUNCTION("spi2", upboard_up_spi2_groups), + UPBOARD_FUNCTION("i2s0", upboard_up_i2s0_groups), + UPBOARD_FUNCTION("pwm0", upboard_up_pwm0_groups), + UPBOARD_FUNCTION("pwm1", upboard_up_pwm1_groups), + UPBOARD_FUNCTION("adc0", upboard_up_adc0_groups), +}; + +static const struct upboard_pinctrl_data upboard_up_pinctrl_data =3D { + .groups =3D &upboard_up_pin_groups[0], + .ngroups =3D ARRAY_SIZE(upboard_up_pin_groups), + .funcs =3D &upboard_up_pin_functions[0], + .nfuncs =3D ARRAY_SIZE(upboard_up_pin_functions), + .pin_header =3D &upboard_up_pin_header[0], + .ngpio =3D ARRAY_SIZE(upboard_up_pin_header), +}; + +#define UPBOARD_UP2_BIT_TO_PIN(bit) UPBOARD_UP2_BIT_##bit + +#define UPBOARD_UP2_PIN_NAME(id) \ + { \ + .number =3D UPBOARD_UP2_BIT_##id, \ + .name =3D #id, \ + } + +#define UPBOARD_UP2_PIN_MUX(bit, data) \ + { \ + .number =3D UPBOARD_UP2_BIT_##bit, \ + .name =3D "PINMUX_"#bit, \ + .drv_data =3D (void *)(data), \ + } + +#define UPBOARD_UP2_PIN_FUNC(id, data) \ + { \ + .number =3D UPBOARD_UP2_BIT_##id, \ + .name =3D #id, \ + .drv_data =3D (void *)(data), \ + } + +enum upboard_up2_fpgabit { + UPBOARD_UP2_BIT_UART1_TXD, + UPBOARD_UP2_BIT_UART1_RXD, + UPBOARD_UP2_BIT_UART1_RTS, + UPBOARD_UP2_BIT_UART1_CTS, + UPBOARD_UP2_BIT_GPIO3_ADC0, + UPBOARD_UP2_BIT_GPIO5_ADC2, + UPBOARD_UP2_BIT_GPIO6_ADC3, + UPBOARD_UP2_BIT_GPIO11, + UPBOARD_UP2_BIT_EXHAT_LVDS1n, + UPBOARD_UP2_BIT_EXHAT_LVDS1p, + UPBOARD_UP2_BIT_SPI2_TXD, + UPBOARD_UP2_BIT_SPI2_RXD, + UPBOARD_UP2_BIT_SPI2_FS1, + UPBOARD_UP2_BIT_SPI2_FS0, + UPBOARD_UP2_BIT_SPI2_CLK, + UPBOARD_UP2_BIT_SPI1_TXD, + UPBOARD_UP2_BIT_SPI1_RXD, + UPBOARD_UP2_BIT_SPI1_FS1, + UPBOARD_UP2_BIT_SPI1_FS0, + UPBOARD_UP2_BIT_SPI1_CLK, + UPBOARD_UP2_BIT_I2C0_SCL, + UPBOARD_UP2_BIT_I2C0_SDA, + UPBOARD_UP2_BIT_I2C1_SCL, + UPBOARD_UP2_BIT_I2C1_SDA, + UPBOARD_UP2_BIT_PWM1, + UPBOARD_UP2_BIT_PWM0, + UPBOARD_UP2_BIT_EXHAT_LVDS0n, + UPBOARD_UP2_BIT_EXHAT_LVDS0p, + UPBOARD_UP2_BIT_GPIO24, + UPBOARD_UP2_BIT_GPIO10, + UPBOARD_UP2_BIT_GPIO2, + UPBOARD_UP2_BIT_GPIO1, + UPBOARD_UP2_BIT_EXHAT_LVDS3n, + UPBOARD_UP2_BIT_EXHAT_LVDS3p, + UPBOARD_UP2_BIT_EXHAT_LVDS4n, + UPBOARD_UP2_BIT_EXHAT_LVDS4p, + UPBOARD_UP2_BIT_EXHAT_LVDS5n, + UPBOARD_UP2_BIT_EXHAT_LVDS5p, + UPBOARD_UP2_BIT_I2S_SDO, + UPBOARD_UP2_BIT_I2S_SDI, + UPBOARD_UP2_BIT_I2S_WS_SYNC, + UPBOARD_UP2_BIT_I2S_BCLK, + UPBOARD_UP2_BIT_EXHAT_LVDS6n, + UPBOARD_UP2_BIT_EXHAT_LVDS6p, + UPBOARD_UP2_BIT_EXHAT_LVDS7n, + UPBOARD_UP2_BIT_EXHAT_LVDS7p, + UPBOARD_UP2_BIT_EXHAT_LVDS2n, + UPBOARD_UP2_BIT_EXHAT_LVDS2p, +}; + +static const struct pinctrl_pin_desc upboard_up2_pins[] =3D { + UPBOARD_UP2_PIN_NAME(UART1_TXD), + UPBOARD_UP2_PIN_NAME(UART1_RXD), + UPBOARD_UP2_PIN_NAME(UART1_RTS), + UPBOARD_UP2_PIN_NAME(UART1_CTS), + UPBOARD_UP2_PIN_NAME(GPIO3_ADC0), + UPBOARD_UP2_PIN_NAME(GPIO5_ADC2), + UPBOARD_UP2_PIN_NAME(GPIO6_ADC3), + UPBOARD_UP2_PIN_NAME(GPIO11), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS1n), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS1p), + UPBOARD_UP2_PIN_NAME(SPI2_TXD), + UPBOARD_UP2_PIN_NAME(SPI2_RXD), + UPBOARD_UP2_PIN_NAME(SPI2_FS1), + UPBOARD_UP2_PIN_NAME(SPI2_FS0), + UPBOARD_UP2_PIN_NAME(SPI2_CLK), + UPBOARD_UP2_PIN_NAME(SPI1_TXD), + UPBOARD_UP2_PIN_NAME(SPI1_RXD), + UPBOARD_UP2_PIN_NAME(SPI1_FS1), + UPBOARD_UP2_PIN_NAME(SPI1_FS0), + UPBOARD_UP2_PIN_NAME(SPI1_CLK), + UPBOARD_UP2_PIN_MUX(I2C0_SCL, &upboard_i2c0_reg), + UPBOARD_UP2_PIN_MUX(I2C0_SDA, &upboard_i2c0_reg), + UPBOARD_UP2_PIN_MUX(I2C1_SCL, &upboard_i2c1_reg), + UPBOARD_UP2_PIN_MUX(I2C1_SDA, &upboard_i2c1_reg), + UPBOARD_UP2_PIN_NAME(PWM1), + UPBOARD_UP2_PIN_NAME(PWM0), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS0n), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS0p), + UPBOARD_UP2_PIN_MUX(GPIO24, &upboard_i2c0_reg), + UPBOARD_UP2_PIN_MUX(GPIO10, &upboard_i2c0_reg), + UPBOARD_UP2_PIN_MUX(GPIO2, &upboard_i2c1_reg), + UPBOARD_UP2_PIN_MUX(GPIO1, &upboard_i2c1_reg), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS3n), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS3p), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS4n), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS4p), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS5n), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS5p), + UPBOARD_UP2_PIN_NAME(I2S_SDO), + UPBOARD_UP2_PIN_NAME(I2S_SDI), + UPBOARD_UP2_PIN_NAME(I2S_WS_SYNC), + UPBOARD_UP2_PIN_NAME(I2S_BCLK), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS6n), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS6p), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS7n), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS7p), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS2n), + UPBOARD_UP2_PIN_NAME(EXHAT_LVDS2p), +}; + +static const unsigned int upboard_up2_pin_header[] =3D { + UPBOARD_UP2_BIT_TO_PIN(GPIO10), + UPBOARD_UP2_BIT_TO_PIN(GPIO24), + UPBOARD_UP2_BIT_TO_PIN(GPIO1), + UPBOARD_UP2_BIT_TO_PIN(GPIO2), + UPBOARD_UP2_BIT_TO_PIN(GPIO3_ADC0), + UPBOARD_UP2_BIT_TO_PIN(GPIO11), + UPBOARD_UP2_BIT_TO_PIN(SPI2_CLK), + UPBOARD_UP2_BIT_TO_PIN(SPI1_FS1), + UPBOARD_UP2_BIT_TO_PIN(SPI1_FS0), + UPBOARD_UP2_BIT_TO_PIN(SPI1_RXD), + UPBOARD_UP2_BIT_TO_PIN(SPI1_TXD), + UPBOARD_UP2_BIT_TO_PIN(SPI1_CLK), + UPBOARD_UP2_BIT_TO_PIN(PWM0), + UPBOARD_UP2_BIT_TO_PIN(PWM1), + UPBOARD_UP2_BIT_TO_PIN(UART1_TXD), + UPBOARD_UP2_BIT_TO_PIN(UART1_RXD), + UPBOARD_UP2_BIT_TO_PIN(UART1_CTS), + UPBOARD_UP2_BIT_TO_PIN(UART1_RTS), + UPBOARD_UP2_BIT_TO_PIN(I2S_BCLK), + UPBOARD_UP2_BIT_TO_PIN(I2S_WS_SYNC), + UPBOARD_UP2_BIT_TO_PIN(I2S_SDI), + UPBOARD_UP2_BIT_TO_PIN(I2S_SDO), + UPBOARD_UP2_BIT_TO_PIN(GPIO6_ADC3), + UPBOARD_UP2_BIT_TO_PIN(SPI2_FS1), + UPBOARD_UP2_BIT_TO_PIN(SPI2_RXD), + UPBOARD_UP2_BIT_TO_PIN(SPI2_TXD), + UPBOARD_UP2_BIT_TO_PIN(SPI2_FS0), + UPBOARD_UP2_BIT_TO_PIN(GPIO5_ADC2), +}; + +static const unsigned int upboard_up2_uart1_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(UART1_TXD), + UPBOARD_UP2_BIT_TO_PIN(UART1_RXD), + UPBOARD_UP2_BIT_TO_PIN(UART1_RTS), + UPBOARD_UP2_BIT_TO_PIN(UART1_CTS), +}; + +static const enum upboard_pin_mode upboard_up2_uart1_modes[] =3D { + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_IN, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_IN, +}; + +static_assert(ARRAY_SIZE(upboard_up2_uart1_modes) =3D=3D ARRAY_SIZE(upboar= d_up2_uart1_pins)); + +static const unsigned int upboard_up2_i2c0_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(I2C0_SCL), + UPBOARD_UP2_BIT_TO_PIN(I2C0_SDA), + UPBOARD_UP2_BIT_TO_PIN(GPIO24), + UPBOARD_UP2_BIT_TO_PIN(GPIO10), +}; + +static const unsigned int upboard_up2_i2c1_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(I2C1_SCL), + UPBOARD_UP2_BIT_TO_PIN(I2C1_SDA), + UPBOARD_UP2_BIT_TO_PIN(GPIO2), + UPBOARD_UP2_BIT_TO_PIN(GPIO1), +}; + +static const unsigned int upboard_up2_spi1_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(SPI1_TXD), + UPBOARD_UP2_BIT_TO_PIN(SPI1_RXD), + UPBOARD_UP2_BIT_TO_PIN(SPI1_FS1), + UPBOARD_UP2_BIT_TO_PIN(SPI1_FS0), + UPBOARD_UP2_BIT_TO_PIN(SPI1_CLK), +}; + +static const unsigned int upboard_up2_spi2_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(SPI2_TXD), + UPBOARD_UP2_BIT_TO_PIN(SPI2_RXD), + UPBOARD_UP2_BIT_TO_PIN(SPI2_FS1), + UPBOARD_UP2_BIT_TO_PIN(SPI2_FS0), + UPBOARD_UP2_BIT_TO_PIN(SPI2_CLK), +}; + +static const enum upboard_pin_mode upboard_up2_spi_modes[] =3D { + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_IN, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_OUT, +}; + +static_assert(ARRAY_SIZE(upboard_up2_spi_modes) =3D=3D ARRAY_SIZE(upboard_= up2_spi1_pins)); + +static_assert(ARRAY_SIZE(upboard_up2_spi_modes) =3D=3D ARRAY_SIZE(upboard_= up2_spi2_pins)); + +static const unsigned int upboard_up2_i2s0_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(I2S_BCLK), + UPBOARD_UP2_BIT_TO_PIN(I2S_WS_SYNC), + UPBOARD_UP2_BIT_TO_PIN(I2S_SDI), + UPBOARD_UP2_BIT_TO_PIN(I2S_SDO), +}; + +static const enum upboard_pin_mode upboard_up2_i2s0_modes[] =3D { + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_OUT, + UPBOARD_PIN_MODE_GPIO_IN, + UPBOARD_PIN_MODE_GPIO_OUT, +}; + +static_assert(ARRAY_SIZE(upboard_up2_i2s0_modes) =3D=3D ARRAY_SIZE(upboard= _up2_i2s0_pins)); + +static const unsigned int upboard_up2_pwm0_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(PWM0), +}; + +static const unsigned int upboard_up2_pwm1_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(PWM1), +}; + +static const unsigned int upboard_up2_adc0_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(GPIO3_ADC0), +}; + +static const unsigned int upboard_up2_adc2_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(GPIO5_ADC2), +}; + +static const unsigned int upboard_up2_adc3_pins[] =3D { + UPBOARD_UP2_BIT_TO_PIN(GPIO6_ADC3), +}; + +static const struct upboard_pingroup upboard_up2_pin_groups[] =3D { + UPBOARD_PINGROUP("uart1_grp", upboard_up2_uart1_pins, &upboard_up2_uart1_= modes[0]), + UPBOARD_PINGROUP("i2c0_grp", upboard_up2_i2c0_pins, UPBOARD_PIN_MODE_FUNC= TION), + UPBOARD_PINGROUP("i2c1_grp", upboard_up2_i2c1_pins, UPBOARD_PIN_MODE_FUNC= TION), + UPBOARD_PINGROUP("spi1_grp", upboard_up2_spi1_pins, &upboard_up2_spi_mode= s[0]), + UPBOARD_PINGROUP("spi2_grp", upboard_up2_spi2_pins, &upboard_up2_spi_mode= s[0]), + UPBOARD_PINGROUP("i2s0_grp", upboard_up2_i2s0_pins, &upboard_up2_i2s0_mod= es[0]), + UPBOARD_PINGROUP("pwm0_grp", upboard_up2_pwm0_pins, UPBOARD_PIN_MODE_GPIO= _OUT), + UPBOARD_PINGROUP("pwm1_grp", upboard_up2_pwm1_pins, UPBOARD_PIN_MODE_GPIO= _OUT), + UPBOARD_PINGROUP("adc0_grp", upboard_up2_adc0_pins, UPBOARD_PIN_MODE_GPIO= _IN), + UPBOARD_PINGROUP("adc2_grp", upboard_up2_adc2_pins, UPBOARD_PIN_MODE_GPIO= _IN), + UPBOARD_PINGROUP("adc3_grp", upboard_up2_adc3_pins, UPBOARD_PIN_MODE_GPIO= _IN), +}; + +static const char * const upboard_up2_uart1_groups[] =3D { "uart1_grp" }; +static const char * const upboard_up2_i2c0_groups[] =3D { "i2c0_grp" }; +static const char * const upboard_up2_i2c1_groups[] =3D { "i2c1_grp" }; +static const char * const upboard_up2_spi1_groups[] =3D { "spi1_grp" }; +static const char * const upboard_up2_spi2_groups[] =3D { "spi2_grp" }; +static const char * const upboard_up2_i2s0_groups[] =3D { "i2s0_grp" }; +static const char * const upboard_up2_pwm0_groups[] =3D { "pwm0_grp" }; +static const char * const upboard_up2_pwm1_groups[] =3D { "pwm1_grp" }; +static const char * const upboard_up2_adc0_groups[] =3D { "adc0_grp" }; +static const char * const upboard_up2_adc2_groups[] =3D { "adc2_grp" }; +static const char * const upboard_up2_adc3_groups[] =3D { "adc3_grp" }; + +static const struct pinfunction upboard_up2_pin_functions[] =3D { + UPBOARD_FUNCTION("uart1", upboard_up2_uart1_groups), + UPBOARD_FUNCTION("i2c0", upboard_up2_i2c0_groups), + UPBOARD_FUNCTION("i2c1", upboard_up2_i2c1_groups), + UPBOARD_FUNCTION("spi1", upboard_up2_spi1_groups), + UPBOARD_FUNCTION("spi2", upboard_up2_spi2_groups), + UPBOARD_FUNCTION("i2s0", upboard_up2_i2s0_groups), + UPBOARD_FUNCTION("pwm0", upboard_up2_pwm0_groups), + UPBOARD_FUNCTION("pwm1", upboard_up2_pwm1_groups), + UPBOARD_FUNCTION("adc0", upboard_up2_adc0_groups), + UPBOARD_FUNCTION("adc2", upboard_up2_adc2_groups), + UPBOARD_FUNCTION("adc3", upboard_up2_adc3_groups), +}; + +static const struct upboard_pinctrl_data upboard_up2_pinctrl_data =3D { + .groups =3D &upboard_up2_pin_groups[0], + .ngroups =3D ARRAY_SIZE(upboard_up2_pin_groups), + .funcs =3D &upboard_up2_pin_functions[0], + .nfuncs =3D ARRAY_SIZE(upboard_up2_pin_functions), + .pin_header =3D &upboard_up2_pin_header[0], + .ngpio =3D ARRAY_SIZE(upboard_up2_pin_header), +}; + +static int upboard_pinctrl_set_function(struct pinctrl_dev *pctldev, unsig= ned int offset) +{ + struct upboard_pinctrl *pctrl =3D pinctrl_dev_get_drvdata(pctldev); + struct upboard_pin *p =3D &pctrl->pins[offset]; + int ret; + + if (!p->funcbit) + return -EPERM; + + ret =3D regmap_field_write(p->enbit, 0); + if (ret) + return ret; + + return regmap_field_write(p->funcbit, 1); +} + +static int upboard_pinctrl_gpio_commit_enable(struct pinctrl_dev *pctldev,= unsigned int offset) +{ + struct upboard_pinctrl *pctrl =3D pinctrl_dev_get_drvdata(pctldev); + struct upboard_pin *p =3D &pctrl->pins[offset]; + int ret; + + if (p->funcbit) { + ret =3D regmap_field_write(p->funcbit, 0); + if (ret) + return ret; + } + + return regmap_field_write(p->enbit, 1); +} + +static int upboard_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + return upboard_pinctrl_gpio_commit_enable(pctldev, offset); +} + +static void upboard_pinctrl_gpio_commit_disable(struct pinctrl_dev *pctlde= v, unsigned int offset) +{ + struct upboard_pinctrl *pctrl =3D pinctrl_dev_get_drvdata(pctldev); + struct upboard_pin *p =3D &pctrl->pins[offset]; + + regmap_field_write(p->enbit, 0); +}; + +static void upboard_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned int offset) +{ + return upboard_pinctrl_gpio_commit_disable(pctldev, offset); +} + +static int upboard_pinctrl_gpio_commit_direction(struct pinctrl_dev *pctld= ev, unsigned int offset, + bool input) +{ + struct upboard_pinctrl *pctrl =3D pinctrl_dev_get_drvdata(pctldev); + struct upboard_pin *p =3D &pctrl->pins[offset]; + + return regmap_field_write(p->dirbit, input); +} + +static int upboard_pinctrl_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset, bool input) +{ + return upboard_pinctrl_gpio_commit_direction(pctldev, offset, input); +} + +static int upboard_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned i= nt func_selector, + unsigned int group_selector) +{ + struct upboard_pinctrl *pctrl =3D pinctrl_dev_get_drvdata(pctldev); + const struct upboard_pinctrl_data *pctrl_data =3D pctrl->pctrl_data; + const struct upboard_pingroup *upgroups =3D pctrl_data->groups; + struct group_desc *grp; + unsigned int mode, i; + int ret; + + grp =3D pinctrl_generic_get_group(pctldev, group_selector); + if (!grp) + return -EINVAL; + + for (i =3D 0; i < grp->grp.npins; i++) { + mode =3D upgroups[group_selector].mode ?: upgroups[group_selector].modes= [i]; + if (mode =3D=3D UPBOARD_PIN_MODE_FUNCTION) { + ret =3D upboard_pinctrl_set_function(pctldev, grp->grp.pins[i]); + if (ret) + return ret; + + continue; + } + + ret =3D upboard_pinctrl_gpio_commit_enable(pctldev, grp->grp.pins[i]); + if (ret) + return ret; + + ret =3D upboard_pinctrl_gpio_commit_direction(pctldev, grp->grp.pins[i], + mode =3D=3D UPBOARD_PIN_MODE_GPIO_IN); + if (ret) + return ret; + } + + return 0; +} + +static const struct pinmux_ops upboard_pinmux_ops =3D { + .get_functions_count =3D pinmux_generic_get_function_count, + .get_function_name =3D pinmux_generic_get_function_name, + .get_function_groups =3D pinmux_generic_get_function_groups, + .set_mux =3D upboard_pinctrl_set_mux, + .gpio_request_enable =3D upboard_pinctrl_gpio_request_enable, + .gpio_disable_free =3D upboard_pinctrl_gpio_disable_free, + .gpio_set_direction =3D upboard_pinctrl_gpio_set_direction, +}; + +static int upboard_pinctrl_pin_get_mode(struct pinctrl_dev *pctldev, unsig= ned int pin) +{ + struct upboard_pinctrl *pctrl =3D pinctrl_dev_get_drvdata(pctldev); + struct upboard_pin *p =3D &pctrl->pins[pin]; + unsigned int val; + int ret; + + if (p->funcbit) { + ret =3D regmap_field_read(p->funcbit, &val); + if (ret) + return ret; + if (val) + return UPBOARD_PIN_MODE_FUNCTION; + } + + ret =3D regmap_field_read(p->enbit, &val); + if (ret) + return ret; + if (!val) + return UPBOARD_PIN_MODE_DISABLED; + + ret =3D regmap_field_read(p->dirbit, &val); + if (ret) + return ret; + + return val ? UPBOARD_PIN_MODE_GPIO_IN : UPBOARD_PIN_MODE_GPIO_OUT; +} + +static void upboard_pinctrl_dbg_show(struct pinctrl_dev *pctldev, struct s= eq_file *s, + unsigned int offset) +{ + int ret; + + ret =3D upboard_pinctrl_pin_get_mode(pctldev, offset); + if (ret =3D=3D UPBOARD_PIN_MODE_FUNCTION) + seq_puts(s, "mode function "); + else if (ret =3D=3D UPBOARD_PIN_MODE_DISABLED) + seq_puts(s, "HIGH-Z "); + else + seq_printf(s, "GPIO (%s) ", str_input_output(ret =3D=3D UPBOARD_PIN_MODE= _GPIO_IN)); +} + +static const struct pinctrl_ops upboard_pinctrl_ops =3D { + .get_groups_count =3D pinctrl_generic_get_group_count, + .get_group_name =3D pinctrl_generic_get_group_name, + .get_group_pins =3D pinctrl_generic_get_group_pins, + .pin_dbg_show =3D upboard_pinctrl_dbg_show, +}; + +static int upboard_gpio_request(struct gpio_chip *gc, unsigned int offset) +{ + struct gpiochip_fwd *fwd =3D gpiochip_get_data(gc); + struct upboard_pinctrl *pctrl =3D gpio_fwd_get_data(fwd); + unsigned int pin =3D pctrl->pctrl_data->pin_header[offset]; + struct gpio_desc *desc; + int ret; + + ret =3D pinctrl_gpio_request(gc, offset); + if (ret) + return ret; + + desc =3D gpiod_get_index(pctrl->dev, "external", pin, 0); + if (IS_ERR(desc)) { + pinctrl_gpio_free(gc, offset); + return PTR_ERR(desc); + } + + return gpio_fwd_gpio_add(fwd, desc, offset); +} + +static void upboard_gpio_free(struct gpio_chip *gc, unsigned int offset) +{ + struct gpiochip_fwd *fwd =3D gpiochip_get_data(gc); + + gpio_fwd_gpio_free(fwd, offset); + pinctrl_gpio_free(gc, offset); +} + +static int upboard_gpio_get_direction(struct gpio_chip *gc, unsigned int o= ffset) +{ + struct gpiochip_fwd *fwd =3D gpiochip_get_data(gc); + struct upboard_pinctrl *pctrl =3D gpio_fwd_get_data(fwd); + unsigned int pin =3D pctrl->pctrl_data->pin_header[offset]; + int mode; + + /* If the pin is in function mode or high-z, input direction is returned = */ + mode =3D upboard_pinctrl_pin_get_mode(pctrl->pctldev, pin); + if (mode < 0) + return mode; + + if (mode =3D=3D UPBOARD_PIN_MODE_GPIO_OUT) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; +} + +static int upboard_gpio_direction_input(struct gpio_chip *gc, unsigned int= offset) +{ + int ret; + + ret =3D pinctrl_gpio_direction_input(gc, offset); + if (ret) + return ret; + + return gpio_fwd_direction_input(gc, offset); +} + +static int upboard_gpio_direction_output(struct gpio_chip *gc, unsigned in= t offset, int value) +{ + int ret; + + ret =3D pinctrl_gpio_direction_output(gc, offset); + if (ret) + return ret; + + return gpio_fwd_direction_output(gc, offset, value); +} + +static int upboard_pinctrl_register_groups(struct upboard_pinctrl *pctrl) +{ + const struct upboard_pingroup *groups =3D pctrl->pctrl_data->groups; + size_t ngroups =3D pctrl->pctrl_data->ngroups; + unsigned int i; + int ret; + + for (i =3D 0; i < ngroups; i++) { + ret =3D pinctrl_generic_add_group(pctrl->pctldev, groups[i].grp.name, + groups[i].grp.pins, groups[i].grp.npins, pctrl); + if (ret < 0) + return ret; + } + + return 0; +} + +static int upboard_pinctrl_register_functions(struct upboard_pinctrl *pctr= l) +{ + const struct pinfunction *funcs =3D pctrl->pctrl_data->funcs; + size_t nfuncs =3D pctrl->pctrl_data->nfuncs; + unsigned int i; + int ret; + + for (i =3D 0; i < nfuncs ; i++) { + ret =3D pinmux_generic_add_function(pctrl->pctldev, funcs[i].name, + funcs[i].groups, funcs[i].ngroups, NULL); + if (ret < 0) + return ret; + } + + return 0; +} + +static const struct pinctrl_map upboard_pinctrl_mapping_apl01[] =3D { + PIN_MAP_MUX_GROUP_DEFAULT("upboard-pinctrl", "INT3452:00", "pwm0_grp", "p= wm0"), + PIN_MAP_MUX_GROUP_DEFAULT("upboard-pinctrl", "INT3452:00", "pwm1_grp", "p= wm1"), + PIN_MAP_MUX_GROUP_DEFAULT("upboard-pinctrl", "INT3452:00", "uart1_grp", "= uart1"), + PIN_MAP_MUX_GROUP_DEFAULT("upboard-pinctrl", "INT3452:02", "i2c0_grp", "i= 2c0"), + PIN_MAP_MUX_GROUP_DEFAULT("upboard-pinctrl", "INT3452:02", "i2c1_grp", "i= 2c1"), + PIN_MAP_MUX_GROUP_DEFAULT("upboard-pinctrl", "INT3452:01", "ssp0_grp", "s= sp0"), +}; + +static const struct dmi_system_id dmi_platform_info[] =3D { + { + /* UP Squared */ + .matches =3D { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "UP-APL01"), + }, + .driver_data =3D (void *)UPBOARD_APL01, + }, + { } +}; + +static int upboard_pinctrl_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct upboard_fpga *fpga =3D dev_get_drvdata(dev->parent); + const struct dmi_system_id *dmi_id; + enum upboard_board_id board_id; + struct pinctrl_desc *pctldesc; + struct upboard_pinctrl *pctrl; + struct upboard_pin *pins; + struct gpiochip_fwd *fwd; + struct pinctrl *pinctrl; + struct gpio_chip *chip; + unsigned int i; + int ret; + + pctldesc =3D devm_kzalloc(dev, sizeof(*pctldesc), GFP_KERNEL); + if (!pctldesc) + return -ENOMEM; + + pctrl =3D devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + + switch (fpga->fpga_data->type) { + case UPBOARD_UP_FPGA: + pctldesc->pins =3D upboard_up_pins; + pctldesc->npins =3D ARRAY_SIZE(upboard_up_pins); + pctrl->pctrl_data =3D &upboard_up_pinctrl_data; + break; + case UPBOARD_UP2_FPGA: + pctldesc->pins =3D upboard_up2_pins; + pctldesc->npins =3D ARRAY_SIZE(upboard_up2_pins); + pctrl->pctrl_data =3D &upboard_up2_pinctrl_data; + break; + default: + return dev_err_probe(dev, -ENODEV, "Unsupported device type %d\n", + fpga->fpga_data->type); + } + + dmi_id =3D dmi_first_match(dmi_platform_info); + if (!dmi_id) + return -ENODEV; + + board_id =3D (enum upboard_board_id)(unsigned long)dmi_id->driver_data; + + switch (board_id) { + case UPBOARD_APL01: + pctrl->maps =3D upboard_pinctrl_mapping_apl01; + pctrl->nmaps =3D ARRAY_SIZE(upboard_pinctrl_mapping_apl01); + break; + default: + return dev_err_probe(dev, -ENODEV, "Unsupported board\n"); + } + + pctldesc->name =3D dev_name(dev); + pctldesc->owner =3D THIS_MODULE; + pctldesc->pctlops =3D &upboard_pinctrl_ops; + pctldesc->pmxops =3D &upboard_pinmux_ops; + + pctrl->dev =3D dev; + + pins =3D devm_kcalloc(dev, pctldesc->npins, sizeof(*pins), GFP_KERNEL); + if (!pins) + return -ENOMEM; + + /* Initialize pins */ + for (i =3D 0; i < pctldesc->npins; i++) { + const struct pinctrl_pin_desc *pin_desc =3D &pctldesc->pins[i]; + unsigned int regoff =3D pin_desc->number / UPBOARD_REGISTER_SIZE; + unsigned int lsb =3D pin_desc->number % UPBOARD_REGISTER_SIZE; + struct reg_field * const fld_func =3D pin_desc->drv_data; + struct upboard_pin *pin =3D &pins[i]; + struct reg_field fldconf =3D {}; + + if (fld_func) { + pin->funcbit =3D devm_regmap_field_alloc(dev, fpga->regmap, *fld_func); + if (IS_ERR(pin->funcbit)) + return PTR_ERR(pin->funcbit); + } + + fldconf.reg =3D UPBOARD_REG_GPIO_EN0 + regoff; + fldconf.lsb =3D lsb; + fldconf.msb =3D lsb; + pin->enbit =3D devm_regmap_field_alloc(dev, fpga->regmap, fldconf); + if (IS_ERR(pin->enbit)) + return PTR_ERR(pin->enbit); + + fldconf.reg =3D UPBOARD_REG_GPIO_DIR0 + regoff; + fldconf.lsb =3D lsb; + fldconf.msb =3D lsb; + pin->dirbit =3D devm_regmap_field_alloc(dev, fpga->regmap, fldconf); + if (IS_ERR(pin->dirbit)) + return PTR_ERR(pin->dirbit); + } + + pctrl->pins =3D pins; + + ret =3D devm_pinctrl_register_and_init(dev, pctldesc, pctrl, &pctrl->pctl= dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to register pinctrl\n"); + + ret =3D upboard_pinctrl_register_groups(pctrl); + if (ret) + return dev_err_probe(dev, ret, "Failed to register groups\n"); + + ret =3D upboard_pinctrl_register_functions(pctrl); + if (ret) + return dev_err_probe(dev, ret, "Failed to register functions\n"); + + ret =3D devm_pinctrl_register_mappings(dev, pctrl->maps, pctrl->nmaps); + if (ret) + return ret; + + pinctrl =3D devm_pinctrl_get_select_default(dev); + if (IS_ERR(pinctrl)) + return dev_err_probe(dev, PTR_ERR(pinctrl), "Failed to select pinctrl\n"= ); + + ret =3D pinctrl_enable(pctrl->pctldev); + if (ret) + return ret; + + fwd =3D devm_gpio_fwd_alloc(dev, pctrl->pctrl_data->ngpio); + if (IS_ERR(fwd)) + return dev_err_probe(dev, PTR_ERR(fwd), "Failed to allocate the gpiochip= forwarder\n"); + + chip =3D gpio_fwd_get_gpiochip(fwd); + chip->request =3D upboard_gpio_request; + chip->free =3D upboard_gpio_free; + chip->get_direction =3D upboard_gpio_get_direction; + chip->direction_output =3D upboard_gpio_direction_output; + chip->direction_input =3D upboard_gpio_direction_input; + + ret =3D gpio_fwd_register(fwd, pctrl); + if (ret) + return dev_err_probe(dev, ret, "Failed to register the gpiochip forwarde= r\n"); + + return gpiochip_add_sparse_pin_range(chip, dev_name(dev), 0, pctrl->pctrl= _data->pin_header, + pctrl->pctrl_data->ngpio); +} + +static struct platform_driver upboard_pinctrl_driver =3D { + .driver =3D { + .name =3D "upboard-pinctrl", + }, + .probe =3D upboard_pinctrl_probe, +}; +module_platform_driver(upboard_pinctrl_driver); + +MODULE_AUTHOR("Thomas Richard