* [PATCH v3] gpio: shared: make the voting mechanism adaptable
From: Bartosz Golaszewski @ 2026-06-30 14:28 UTC (permalink / raw)
To: Marek Vasut, Arnd Bergmann, Bartosz Golaszewski,
Greg Kroah-Hartman, Srinivas Kandagatla, Linus Walleij,
Viacheslav Bocharov
Cc: linux-kernel, linux-gpio, Bartosz Golaszewski
The current voting mechanism in GPIO shared proxy assumes that "low" is
always the default value and users can only vote for driving the GPIO
"high" in which case it will remain high as long as there's at least one
user voting.
This makes it impossible to use the automatic sharing management for
certain use-cases such as the write-protect GPIOs of EEPROMs which are
requested "high" and driven "low" to enable writing. In this case, if
the WP GPIO is shared by multiple EEPROMs, and at least one of them
wants to enable writing, the pin must be set to "low".
Modify the voting heuristic to assume the value set by the first user on
request to be the "default" and subseqent calls to gpiod_set_value()
will constitute votes for a change of the value to the opposite. In the
wp-gpios case it will mean that the nvmem core requests the GPIO as
"out-high" for all EEPROMs sharing the pin, and when one of them wants
to write, the pin will be driven low, enabling it.
Fixes: e992d54c6f97 ("gpio: shared-proxy: implement the shared GPIO proxy driver")
Reported-by: Marek Vasut <marex@nabladev.com>
Closes: https://lore.kernel.org/all/20260511163518.51104-1-marex@nabladev.com/
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
Changes in v3:
- Rebase on top of locking changes in gpio-shared-proxy.c
- Link to v2: https://patch.msgid.link/20260528-gpio-shared-dynamic-voting-v2-1-820837ce8cd2@oss.qualcomm.com
Changes in v2:
- Rebased on top of current linux-next which contains a fix for the
shared GPIO proxy release path
- Link to v1: https://patch.msgid.link/20260513-gpio-shared-dynamic-voting-v1-1-8e1c49961b7d@oss.qualcomm.com
---
drivers/gpio/gpio-shared-proxy.c | 66 +++++++++++++++++++---------------------
drivers/gpio/gpiolib-shared.h | 3 +-
2 files changed, 34 insertions(+), 35 deletions(-)
diff --git a/drivers/gpio/gpio-shared-proxy.c b/drivers/gpio/gpio-shared-proxy.c
index 10ca2ef77ef3410b7be46a6657ebea8cd80c4491..52a366f0ec4de71e9d6b8f88ef77ef007b660c88 100644
--- a/drivers/gpio/gpio-shared-proxy.c
+++ b/drivers/gpio/gpio-shared-proxy.c
@@ -22,7 +22,7 @@ struct gpio_shared_proxy_data {
struct gpio_chip gc;
struct gpio_shared_desc *shared_desc;
struct device *dev;
- bool voted_high;
+ bool voted_change;
};
static int
@@ -34,52 +34,54 @@ gpio_shared_proxy_set_unlocked(struct gpio_shared_proxy_data *proxy, int value)
lockdep_assert_held(&shared_desc->mutex);
- if (value) {
- /* User wants to set value to high. */
- if (proxy->voted_high)
- /* Already voted for high, nothing to do. */
+ if (value != shared_desc->def_val) {
+ /* User wants to vote for a value change. */
+ if (proxy->voted_change)
+ /* Already voted for a change, nothing to do. */
goto out;
- /* Haven't voted for high yet. */
- if (!shared_desc->highcnt) {
+ /* Haven't voted for a value change yet. */
+ if (!shared_desc->votecnt) {
/*
- * Current value is low, need to actually set value
- * to high.
+ * Current value is default, need to actually set value
+ * to the opposite.
*/
- ret = gpiod_set_value_cansleep(desc, 1);
+ ret = gpiod_set_value_cansleep(desc, value);
if (ret)
goto out;
}
- shared_desc->highcnt++;
- proxy->voted_high = true;
+ shared_desc->votecnt++;
+ proxy->voted_change = true;
goto out;
}
- /* Desired value is low. */
- if (!proxy->voted_high)
- /* We didn't vote for high, nothing to do. */
+ /* Desired value is the default. */
+ if (!proxy->voted_change)
+ /* We didn't vote for change previously, nothing to do. */
goto out;
- /* We previously voted for high. */
- if (shared_desc->highcnt == 1) {
- /* This is the last remaining vote for high, set value to low. */
- ret = gpiod_set_value_cansleep(desc, 0);
+ /* We previously voted for change. */
+ if (shared_desc->votecnt == 1) {
+ /* This is the last remaining vote for change, set value to default. */
+ ret = gpiod_set_value_cansleep(desc, shared_desc->def_val);
if (ret)
goto out;
}
- shared_desc->highcnt--;
- proxy->voted_high = false;
+ shared_desc->votecnt--;
+ proxy->voted_change = false;
out:
- if (shared_desc->highcnt)
+ if (shared_desc->votecnt)
dev_dbg(proxy->dev,
- "Voted for value '%s', effective value is 'high', number of votes for 'high': %u\n",
- str_high_low(value), shared_desc->highcnt);
+ "Voted for value '%s', effective value is '%s', number of votes: %u\n",
+ str_high_low(value), str_high_low(!shared_desc->def_val),
+ shared_desc->votecnt);
else
- dev_dbg(proxy->dev, "Voted for value 'low', effective value is 'low'\n");
+ dev_dbg(proxy->dev, "Voted for value '%s', effective value is '%s'\n",
+ str_high_low(value), str_high_low(shared_desc->def_val));
return ret;
}
@@ -107,8 +109,8 @@ static void gpio_shared_proxy_free(struct gpio_chip *gc, unsigned int offset)
guard(mutex)(&shared_desc->mutex);
- if (proxy->voted_high) {
- ret = gpio_shared_proxy_set_unlocked(proxy, 0);
+ if (proxy->voted_change) {
+ ret = gpio_shared_proxy_set_unlocked(proxy, shared_desc->def_val);
if (ret)
dev_err(proxy->dev,
"Failed to unset the shared GPIO value on release: %d\n", ret);
@@ -197,13 +199,9 @@ static int gpio_shared_proxy_direction_output(struct gpio_chip *gc,
if (ret)
return ret;
- if (value) {
- proxy->voted_high = true;
- shared_desc->highcnt = 1;
- } else {
- proxy->voted_high = false;
- shared_desc->highcnt = 0;
- }
+ shared_desc->def_val = value;
+ shared_desc->votecnt = 0;
+ proxy->voted_change = false;
return 0;
}
diff --git a/drivers/gpio/gpiolib-shared.h b/drivers/gpio/gpiolib-shared.h
index bbdc0ab7b647a44fca714bed0a7ff75101da7460..618756f6c6aafd087df267a4a32732ccc03af38e 100644
--- a/drivers/gpio/gpiolib-shared.h
+++ b/drivers/gpio/gpiolib-shared.h
@@ -41,7 +41,8 @@ struct gpio_shared_desc {
struct gpio_desc *desc;
unsigned long cfg;
unsigned int usecnt;
- unsigned int highcnt;
+ unsigned int votecnt;
+ int def_val;
struct mutex mutex; /* serializes all proxy operations on this descriptor */
};
---
base-commit: efecde8a254d1f207b75c5ebcfba2c51f4c771d9
change-id: 20260512-gpio-shared-dynamic-voting-9aab4689f5e9
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply related
* Re: [PATCH v5 0/6] gpiolib: fence off legacy interfaces
From: Bartosz Golaszewski @ 2026-06-30 14:17 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Arnd Bergmann, John Paul Adrian Glaubitz, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
Linus Walleij, Bartosz Golaszewski, Dmitry Torokhov, Lee Jones,
Pavel Machek, linux-sh, linux-kernel, linux-input, linux-leds,
linux-gpio
In-Reply-To: <20260629130329.1291953-1-arnd@kernel.org>
On Mon, 29 Jun 2026 15:03:23 +0200, Arnd Bergmann <arnd@kernel.org> said:
> From: Arnd Bergmann <arnd@arndb.de>
>
> This is the remainder of the series previously posted as v2
> in [1]. I've changed the version to v5 for all patches to
> not confuse b4 too much, but the patches are mostly unchanged.
>
> The patch "Input: soc_button_array - select CONFIG_GPIOLIB_LEGACY"
> was not part of the series last time, but the build bots reported
> this as a regression since I had dropped that since v1.
>
> I hope that all that remains now can just get merged through the
> gpio tree. The gpio-keys patch needs a bit coordination with
> another patch addressing the same issue that is already in
> flight, so I expect that I'll rebase my series once more when
> that is in a stable branch, but the state I have here should
> just work as-is on top of v7.2-rc1.
>
> Arnd
>
> [1] https://lore.kernel.org/all/20260520183815.2510387-1-arnd@kernel.org/
>
> Arnd Bergmann (6):
> [v5] sh: select legacy gpiolib interface
> [v5] x86/olpc: select GPIOLIB_LEGACY
> [v5] Input: soc_button_array - select CONFIG_GPIOLIB_LEGACY
> [v5] Input: gpio-keys: make legacy gpiolib optional
> [v5] leds: gpio: make legacy gpiolib interface optional
> [v5] gpiolib: turn off legacy interface by default
Why this weird formatting?
Anyway, for the series:
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH 0/2] EDITME: cover title for pmg1110-gpio
From: Bartosz Golaszewski @ 2026-06-30 14:16 UTC (permalink / raw)
To: linux-arm-msm, Bjorn Andersson, Linus Walleij, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Fenglin Wu
Cc: Bartosz Golaszewski, David Collins, Subbaraman Narayanamurthy,
Kamal Wadhwa, kernel, linux-gpio, devicetree, linux-kernel,
Konrad Dybcio
In-Reply-To: <20260610-pmg1110-gpio-v1-0-a9c50cd8b5d9@oss.qualcomm.com>
On Wed, 10 Jun 2026 00:05:45 -0700, Fenglin Wu wrote:
>
Applied, thanks!
[1/2] dt-bindings: pinctrl: qcom,pmic-gpio: Document PMG1110 GPIO support
https://git.kernel.org/brgl/c/32bd01532af59cf0cc6994e2794e0aaa9af5bc8d
[2/2] pinctrl: qcom: spmi-gpio: Add PMG1110 GPIO support
https://git.kernel.org/brgl/c/8a762912365d4e7402fb8942934681acd0a3bcd6
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2 3/4] gpio: mt7621: be sure IRQ domain is created before exposing GPIO chips
From: Sergio Paracuellos @ 2026-06-30 14:12 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: linusw, vicencb, linux-kernel, stable, Sashiko, linux-gpio
In-Reply-To: <CAMRc=MfiSePgA+Vc2GHz_5QUGZWFhnPrXPZoCV+32b9RJos5xg@mail.gmail.com>
Hi Bartosz,
On Tue, Jun 30, 2026 at 4:06 PM Bartosz Golaszewski <brgl@kernel.org> wrote:
>
> On Fri, 26 Jun 2026 08:01:11 +0200, Sergio Paracuellos
> <sergio.paracuellos@gmail.com> said:
> > Function 'mediatek_gpio_bank_probe()' registers three GPIO chips using
> > 'devm_gpiochip_add_data()'. At this point, the chips become live and visible
> > to consumers. However, the IRQ domain isn't allocated and set up until
> > 'mt7621_gpio_irq_setup()' is called after the GPIO chips setup finishes.
> > If a consumer requests a GPIO IRQ concurrently 'mt7621_gpio_to_irq()' can
> > be called and pass a NULL irq domain pointer irq_create_mapping(), that can
> > corrupt the mappings or cause a crash. Fix this possible problem seting up
> > irq domain before GPIO chips setup is performed.
> >
> > Cc: stable@vger.kernel.org
> > Reported-by: Sashiko <sashiko-bot@kernel.org>
> > Fixes: a46f2e5720f5 ("gpio: mt7621: fix interrupt banks mapping on gpio chips")
> > Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> > ---
>
> Seems like sashiko still complains about this one. I'm not overly worried about
> this path but since the commit's purpose was to address this very issue, do you
> want to rework it further?
Previous complaint was about the IRQ mapping being NULL because
mapping was not created when gpio chips are set up. I think that it
made more sense that this new complaint about the reverse order. So I
would maintain this PATCH as it is. Thus, I don't want to rework
anything here.
Thanks,
Sergio Paracuellos
^ permalink raw reply
* Re: [PATCH v2 3/4] gpio: mt7621: be sure IRQ domain is created before exposing GPIO chips
From: Bartosz Golaszewski @ 2026-06-30 14:06 UTC (permalink / raw)
To: Sergio Paracuellos
Cc: linusw, brgl, vicencb, linux-kernel, stable, Sashiko, linux-gpio
In-Reply-To: <20260626060112.2498324-4-sergio.paracuellos@gmail.com>
On Fri, 26 Jun 2026 08:01:11 +0200, Sergio Paracuellos
<sergio.paracuellos@gmail.com> said:
> Function 'mediatek_gpio_bank_probe()' registers three GPIO chips using
> 'devm_gpiochip_add_data()'. At this point, the chips become live and visible
> to consumers. However, the IRQ domain isn't allocated and set up until
> 'mt7621_gpio_irq_setup()' is called after the GPIO chips setup finishes.
> If a consumer requests a GPIO IRQ concurrently 'mt7621_gpio_to_irq()' can
> be called and pass a NULL irq domain pointer irq_create_mapping(), that can
> corrupt the mappings or cause a crash. Fix this possible problem seting up
> irq domain before GPIO chips setup is performed.
>
> Cc: stable@vger.kernel.org
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Fixes: a46f2e5720f5 ("gpio: mt7621: fix interrupt banks mapping on gpio chips")
> Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> ---
Seems like sashiko still complains about this one. I'm not overly worried about
this path but since the commit's purpose was to address this very issue, do you
want to rework it further?
Bart
^ permalink raw reply
* Re: (subset) [PATCH v3 0/2] gpio: fix sleeping-in-atomic in shared-proxy; restore meson non-sleeping
From: Bartosz Golaszewski @ 2026-06-30 14:03 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Viacheslav Bocharov
Cc: Bartosz Golaszewski, Neil Armstrong, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Marek Szyprowski, Robin Murphy,
Diederik de Haas, linux-gpio, linux-arm-kernel, linux-amlogic,
linux-kernel
In-Reply-To: <20260630101545.800625-1-v@baodeep.com>
On Tue, 30 Jun 2026 13:15:43 +0300, Viacheslav Bocharov wrote:
> gpio-shared-proxy chooses its descriptor lock (mutex vs spinlock) from
> the underlying chip's can_sleep, but under that lock it calls config and
> direction ops that reach sleeping pinctrl paths. On a controller with
> non-sleeping MMIO value ops the lock is a spinlock, so a sleeping call
> runs from atomic context:
>
> BUG: sleeping function called from invalid context
> ... pinctrl_gpio_set_config <- gpiochip_generic_config
> <- gpio_shared_proxy_set_config (voting spinlock held)
> <- ... <- mmc_pwrseq_simple_probe
>
> [...]
There are no build-time dependencies between this and 2/2 so let me queue this
for fixes on its own and Linus W can take 2/2.
[1/2] gpio: shared-proxy: always serialize with a sleeping mutex
https://git.kernel.org/brgl/c/efecde8a254d1f207b75c5ebcfba2c51f4c771d9
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH 2/2] pinctrl: qcom: Drop unused irq_data argument from msm_gpio_update_dual_edge_pos()
From: Linus Walleij @ 2026-06-30 13:38 UTC (permalink / raw)
To: Hans de Goede; +Cc: Bjorn Andersson, linux-arm-msm, linux-gpio
In-Reply-To: <20260623122732.6439-2-johannes.goede@oss.qualcomm.com>
On Tue, Jun 23, 2026 at 1:27 PM Hans de Goede
<johannes.goede@oss.qualcomm.com> wrote:
> The "struct irq_data *d" argument to msm_gpio_update_dual_edge_pos() is
> unused, drop it.
>
> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Acked-by: Linus Walleij <linusw@kernel.org>
Bartosz will apply this patch!
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 1/2] pinctrl: qcom: Drop unnecessary bitmap_fill() call
From: Linus Walleij @ 2026-06-30 13:37 UTC (permalink / raw)
To: Hans de Goede, Bartosz Golaszewski
Cc: Bjorn Andersson, linux-arm-msm, linux-gpio
In-Reply-To: <20260623122732.6439-1-johannes.goede@oss.qualcomm.com>
On Tue, Jun 23, 2026 at 1:27 PM Hans de Goede
<johannes.goede@oss.qualcomm.com> wrote:
> Drop an unnecessary bitmap_fill() call from msm_gpio_irq_init_valid_mask(),
> this is unnecessary because gpiochip_allocate_mask() already does this.
>
> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Acked-by: Linus Walleij <linusw@kernel.org>
Bartosz will apply this patch!
Yours,
Linus Walleij
^ permalink raw reply
* RE: [PATCH v18 1/4] pinctrl: renesas: rzg2l: Add SD channel POC support for RZ/G3L
From: Biju Das @ 2026-06-30 13:34 UTC (permalink / raw)
To: Linus Walleij, biju.das.au
Cc: Geert Uytterhoeven, linux-renesas-soc@vger.kernel.org,
linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org,
Prabhakar Mahadev Lad
In-Reply-To: <CAD++jLnQ2ty7DtJLOt_FskG18ZsChttswhf=T_Vo4wLhq12_cQ@mail.gmail.com>
Hi Linus Walleij,
> -----Original Message-----
> From: Linus Walleij <linusw@kernel.org>
> Sent: 30 June 2026 14:29
> Subject: Re: [PATCH v18 1/4] pinctrl: renesas: rzg2l: Add SD channel POC support for RZ/G3L
>
> Hi Biju,
>
> thanks for your patch!
>
> On Mon, Jun 22, 2026 at 5:48 PM Biju <biju.das.au@gmail.com> wrote:
>
> > From: Biju Das <biju.das.jz@bp.renesas.com>
> >
> > Add power-on control (POC) support for SD channels 1 and 2 on the
> > RZ/G3L SoC (r9a08g046).
> >
> > Introduce PIN_CFG_IO_VMC_SD2 capability flag (bit 22) and SD_CH2_POC
> > register offset (0x3024). Extend rzg2l_caps_to_pwr_reg() to return
> > SD_CH2_POC when PIN_CFG_IO_VMC_SD2 is set.
> >
> > Replace RZG3L_MPXED_PIN_FUNCS() with RZG2L_MPXED_COMMON_PIN_FUNCS()
> > for port PG and PH pins, dropping PIN_CFG_SOFT_PS which is
> > inappropriate for SD pins, and annotate them with PIN_CFG_IO_VMC_SD1
> > and PIN_CFG_IO_VMC_SD2 respectively.
> >
> > Annotate all RZ/G3L SD0 dedicated pins (CLK, CMD, RST#, DS, DAT0–DAT7)
> > with PIN_CFG_IO_VMC_SD0 so that power-source register lookups work
> > correctly for those pins.
> >
> > Add sd_ch2 field to rzg2l_register_offsets and rzg2l_pinctrl_reg_cache
> > to save and restore the SD_CH2_POC register across suspend/resume cycles.
> >
> > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
>
> Is this patch Geert can apply separately for pin control in the end?
Yes, Geert will apply this patch to renesas-pinctrl tree and
then pull request to you.
Cheers,
Biju
^ permalink raw reply
* Re: [PATCH v18 1/4] pinctrl: renesas: rzg2l: Add SD channel POC support for RZ/G3L
From: Linus Walleij @ 2026-06-30 13:28 UTC (permalink / raw)
To: Biju
Cc: Geert Uytterhoeven, Biju Das, linux-renesas-soc, linux-gpio,
linux-kernel, Prabhakar Mahadev Lad
In-Reply-To: <20260622164819.184674-2-biju.das.jz@bp.renesas.com>
Hi Biju,
thanks for your patch!
On Mon, Jun 22, 2026 at 5:48 PM Biju <biju.das.au@gmail.com> wrote:
> From: Biju Das <biju.das.jz@bp.renesas.com>
>
> Add power-on control (POC) support for SD channels 1 and 2 on the RZ/G3L
> SoC (r9a08g046).
>
> Introduce PIN_CFG_IO_VMC_SD2 capability flag (bit 22) and SD_CH2_POC
> register offset (0x3024). Extend rzg2l_caps_to_pwr_reg() to return
> SD_CH2_POC when PIN_CFG_IO_VMC_SD2 is set.
>
> Replace RZG3L_MPXED_PIN_FUNCS() with RZG2L_MPXED_COMMON_PIN_FUNCS() for
> port PG and PH pins, dropping PIN_CFG_SOFT_PS which is inappropriate for
> SD pins, and annotate them with PIN_CFG_IO_VMC_SD1 and PIN_CFG_IO_VMC_SD2
> respectively.
>
> Annotate all RZ/G3L SD0 dedicated pins (CLK, CMD, RST#, DS, DAT0–DAT7)
> with PIN_CFG_IO_VMC_SD0 so that power-source register lookups work
> correctly for those pins.
>
> Add sd_ch2 field to rzg2l_register_offsets and rzg2l_pinctrl_reg_cache to
> save and restore the SD_CH2_POC register across suspend/resume cycles.
>
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Is this patch Geert can apply separately for pin control in the end?
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v4 00/14] pinctrl: airoha: split driver on shared code and SoC specific drivers, add supporf of en7523
From: Linus Walleij @ 2026-06-30 13:26 UTC (permalink / raw)
To: Mikhail Kshevetskiy
Cc: Lorenzo Bianconi, Christian Marangi, Benjamin Larsson,
AngeloGioacchino Del Regno, linux-kernel, linux-gpio,
linux-mediatek, Markus Gothe, Matheus Sampaio Queiroga
In-Reply-To: <CAD++jLmY6Ase3hPC00z_kAJe+vJBUyrEHZEAOcWqkiuFnRGCcA@mail.gmail.com>
On Tue, Jun 30, 2026 at 1:09 PM Linus Walleij <linusw@kernel.org> wrote:
> On Wed, Jun 17, 2026 at 5:37 AM Mikhail Kshevetskiy
> <mikhail.kshevetskiy@iopsys.eu> wrote:
>
> > This patchset
> > * fixes more airoha pinctrl issues
> > * split combined driver on common code and several SoC specific drivers
> > * improves an7583 pinctrl support
> > * adds support of en7523 SoC
>
> No comments for two weeks so patches applied.
I realized there is v5 and v6 which are still being discussed so I backed
these out.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v5 0/5] Add support for AAEON SRG-IMX8P MCU
From: Thomas Perrot @ 2026-06-30 13:24 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: thomas.perrot, devicetree, linux-kernel, linux-gpio, imx,
linux-arm-kernel, linux-watchdog, Thomas Petazzoni, Miquel Raynal,
Krzysztof Kozlowski, Conor Dooley, Bartosz Golaszewski,
Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Linus Walleij, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Jérémie Dautheribes, Wim Van Sebroeck,
Lee Jones
In-Reply-To: <CAMRc=MdJJnRTOSEecqpX-EddJRAzWc_1a-cg3wrW8m0jR2Fihw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 884 bytes --]
Hello Bartosz,
On Tue, 2026-06-30 at 00:47 -0700, Bartosz Golaszewski wrote:
> On Mon, 29 Jun 2026 18:04:59 +0200, Thomas Perrot
> <thomas.perrot@bootlin.com> said:
> > Hello Guenter,
> >
> > On Sat, 2026-04-11 at 17:12 -0700, Guenter Roeck wrote:
> > > snip
> > >
> > > Sashiko has some interesting feedback that might be worth looking
> > > into.
> > >
> > > https://sashiko.dev/#/patchset/20260408-dev-b4-aaeon-mcu-driver-v5-0-ad98bd481668%40bootlin.com
> > >
> >
> > Thanks for the pointer. I went through all findings and addressed
> > the
> > valid ones in v6:
> >
>
> Did I miss anything? I don't see the v6 neither in my inbox nor on
> lore.
I just submitted it. I was waiting for the tests to finish.
Kind regards,
Thomas Perrot
>
> Bart
--
Thomas Perrot, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply
* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Linus Walleij @ 2026-06-30 13:21 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Michael Walle, Bartosz Golaszewski, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, afaerber@suse.com,
wbg@kernel.org, mathieu.dubois-briand@bootlin.com,
lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org,
nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
TY_Chang[張子逸], linux-gpio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
CY_Huang[黃鉦晏],
Stanley Chang[昌育德],
James Tai [戴志峰],
Yu-Chun Lin [林祐君]
In-Reply-To: <ajkP4DHN4JPjr6yb@ashevche-desk.local>
On Mon, Jun 22, 2026 at 11:35 AM Andy Shevchenko
<andriy.shevchenko@intel.com> wrote:
> So, when we instantiate our own domain in regmap GPIO, we should have those
> callbacks be defined somewhere?
Domains are just translators, but if you create an irq chip it should
ideally have these callbacks.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v4 1/4] dt-bindings: gpio: realtek: Add realtek,rtd1625-gpio
From: Linus Walleij @ 2026-06-30 13:17 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: brgl, robh, krzk+dt, conor+dt, afaerber, mwalle,
andriy.shevchenko, tychang, linux-gpio, devicetree, linux-kernel,
linux-arm-kernel, linux-realtek-soc, cy.huang, stanley_chang,
james.tai, Krzysztof Kozlowski
In-Reply-To: <20260622092335.1166876-2-eleanor.lin@realtek.com>
Hi Yu-Chun,
thanks for your patch!
On Mon, Jun 22, 2026 at 10:33 AM Yu-Chun Lin <eleanor.lin@realtek.com> wrote:
> From: Tzuyi Chang <tychang@realtek.com>
>
> Add the device tree bindings for the Realtek DHC (Digital Home Center)
> RTD1625 GPIO controllers.
>
> The RTD1625 GPIO controller features a per-pin register architecture
> that differs significantly from previous generations. It utilizes
> separate register blocks for GPIO configuration and interrupt control.
>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Tzuyi Chang <tychang@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
(...)
> + interrupt-controller: true
> +
> + "#interrupt-cells":
> + const: 2
> +
> + gpio-ranges: true
> +
> + gpio-controller: true
> +
> + "#gpio-cells":
> + const: 2
After looking at the driver I must challenge this binding.
Your driver is full of (offset % 32) and even (offset % 32) *4 to just
work around the fact that the hardware inherently has 32-pin banks.
Instead of using twocell GPIO and irqs, just use threecell, interrupt-cells
and gpio-cells 3.
First cell is bank, second cell is offset inside each bank.
For Linux specifically there are helpers for dealing with this in gpiolib,
and further you will be able to use the GPIO_GENERIC library,
while this is beside the point for the binding itself.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v2 2/2] dt-bindings: Drop incorrect usage of double '::'
From: Rob Herring (Arm) @ 2026-06-30 13:14 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Sireesh Kodali, Stephen Boyd, Rob Clark, Wesley Cheng, Vinod Koul,
Seung-Woo Kim, Michael Turquette, freedreno, Linus Walleij,
Sam Protsenko, Rafael J. Wysocki, Alim Akhtar, linux-gpio,
linux-arm-msm, Taniya Das, Liam Girdwood, Imran Shaik, linux-phy,
Christian Marangi, Sebastian Reichel, Luo Jie,
Niklas Söderlund, Bjorn Andersson, Niklas Söderlund,
linux-kernel, linux-arm-kernel, dri-devel, Magnus Damm,
Conor Dooley, Brian Masney, linux-serial, linux-mmc, Sean Paul,
Kyungmin Park, Krishna Manikandan, linux-i2c, Konrad Dybcio,
Sylwester Nawrocki, Bartlomiej Zolnierkiewicz, Hans Verkuil,
Krzysztof Kozlowski, Chanwoo Choi, Sricharan Ramabadhran,
Andy Gross, Simona Vetter, Jaehoon Chung, Mauro Carvalho Chehab,
Zhang Rui, Maarten Lankhorst, Jessica Zhang, Tomasz Figa,
Shin Son, Marek Szyprowski, Robert Marko, linux-leds, Lee Jones,
Lukasz Luba, Srinivas Kandagatla, Georgi Djakov, Barnabas Czeman,
Greg Kroah-Hartman, Anusha Rao, linux-sound, Neil Armstrong,
linux-pm, Jiri Slaby, Marijn Suijten, Stephan Gerhold, linux-clk,
Mark Brown, Maxime Ripard, Pavel Machek, David Airlie,
Geert Uytterhoeven, Sunyeal Hong, Peter Griffin,
Sebastian Reichel, Andi Shyti, Dmitry Baryshkov, linux-usb,
Thomas Zimmermann, Jacek Anaszewski, Daniel Lezcano, Alina Yu,
Abhinav Kumar, Adam Skladowski, Conor Dooley,
Javier Martinez Canillas, Jonathan Marek, linux-renesas-soc,
linux-samsung-soc, Inki Dae, linux-media, Ulf Hansson,
Chanho Park, devicetree
In-Reply-To: <20260623054842.21831-4-krzysztof.kozlowski@oss.qualcomm.com>
On Tue, 23 Jun 2026 07:48:44 +0200, Krzysztof Kozlowski wrote:
> There is no use of double colon '::' in YAML. OTOH, the literal style
> block, e.g. using '|' treats all characters as content [1] therefore
> single use of ':' in descriptions is perfectly fine, whenever '|' is
> used.
>
> Cleanup existing code, so the confusing style won't be re-used in new
> contributions.
>
> Link: https://yaml.org/spec/1.2.2/#literal-style [1]
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Acked-by: Alim Akhtar <alim.akhtar@samsung.com>
> Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
> Acked-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Acked-by: Mark Brown <broonie@kernel.org>
> Acked-by: Geert Uytterhoeven <geert+renesas@glider.be> # renesas
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>
> ---
>
> Intention for this patch is to go via Rob's tree.
>
> Changes in v2:
> 1. Add tags (partial Reviews as Acks, as that's the meaning of Ack)
> 2. Do not replace ::= in mux.
> ---
> .../devicetree/bindings/arm/qcom-soc.yaml | 4 ++--
> .../devicetree/bindings/arm/qcom.yaml | 4 ++--
> .../bindings/arm/samsung/samsung-soc.yaml | 4 ++--
> .../display/msm/dsi-controller-main.yaml | 20 +++++++++----------
> .../display/samsung/samsung,fimd.yaml | 4 ++--
> .../bindings/i2c/samsung,s3c2410-i2c.yaml | 2 +-
> .../interconnect/qcom,msm8998-bwmon.yaml | 2 +-
> .../interconnect/samsung,exynos-bus.yaml | 14 ++++++-------
> .../bindings/leds/qcom,pm8058-led.yaml | 4 ++--
> .../bindings/leds/skyworks,aat1290.yaml | 6 +++---
> .../bindings/media/cec/cec-gpio.yaml | 2 +-
> .../bindings/mmc/samsung,exynos-dw-mshc.yaml | 2 +-
> .../bindings/phy/samsung,mipi-video-phy.yaml | 4 ++--
> .../bindings/phy/samsung,usb2-phy.yaml | 2 +-
> .../bindings/phy/samsung,usb3-drd-phy.yaml | 2 +-
> .../bindings/pinctrl/samsung,pinctrl.yaml | 2 +-
> .../bindings/power/renesas,rcar-sysc.yaml | 2 +-
> .../bindings/power/reset/restart-handler.yaml | 8 ++++----
> .../bindings/regulator/maxim,max77802.yaml | 4 ++--
> .../bindings/regulator/richtek,rtq2208.yaml | 2 +-
> .../bindings/serial/qcom,msm-uartdm.yaml | 2 +-
> .../devicetree/bindings/slimbus/slimbus.yaml | 4 ++--
> .../bindings/soc/qcom/qcom,apr-services.yaml | 2 +-
> .../bindings/soc/qcom/qcom,rpmh-rsc.yaml | 8 ++++----
> .../bindings/soc/qcom/qcom,wcnss.yaml | 2 +-
> .../bindings/soc/renesas/renesas-soc.yaml | 4 ++--
> .../bindings/sound/qcom,q6asm-dais.yaml | 2 +-
> .../thermal/samsung,exynos-thermal.yaml | 4 ++--
> .../devicetree/bindings/usb/qcom,dwc3.yaml | 12 +++++------
> .../bindings/usb/qcom,snps-dwc3.yaml | 12 +++++------
> 30 files changed, 73 insertions(+), 73 deletions(-)
>
Applied, thanks!
^ permalink raw reply
* Re: [PATCH v2 1/2] dt-bindings: clock: Drop incorrect usage of double '::'
From: Rob Herring (Arm) @ 2026-06-30 13:14 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Lee Jones, Sean Paul, Krzysztof Kozlowski, David Airlie,
Kyungmin Park, Lukasz Luba, Vinod Koul, Adam Skladowski,
Chanho Park, Wesley Cheng, Mark Brown, Linus Walleij, Alim Akhtar,
Abhinav Kumar, linux-gpio, linux-samsung-soc, Anusha Rao,
linux-mmc, Jonathan Marek, Greg Kroah-Hartman,
Javier Martinez Canillas, Taniya Das, linux-clk, Stephen Boyd,
linux-kernel, Zhang Rui, Srinivas Kandagatla, Barnabas Czeman,
Bjorn Andersson, Sunyeal Hong, freedreno, Stephan Gerhold,
Rob Clark, Simona Vetter, Andi Shyti, Niklas Söderlund,
linux-i2c, Brian Masney, Mauro Carvalho Chehab, Maarten Lankhorst,
Konrad Dybcio, Maxime Ripard, Daniel Lezcano, Rafael J. Wysocki,
Hans Verkuil, Dmitry Baryshkov, Sebastian Reichel, Chanwoo Choi,
Robert Marko, linux-sound, linux-usb, Pavel Machek, Peter Griffin,
linux-arm-msm, Marijn Suijten, Christian Marangi, Imran Shaik,
Neil Armstrong, dri-devel, Jiri Slaby, linux-phy, Shin Son,
Jessica Zhang, Liam Girdwood, Sam Protsenko, Tomasz Figa,
Magnus Damm, linux-renesas-soc, Jacek Anaszewski,
Sricharan Ramabadhran, Georgi Djakov, Conor Dooley,
Geert Uytterhoeven, devicetree, Luo Jie, linux-serial,
Jaehoon Chung, Andy Gross, Krishna Manikandan, Thomas Zimmermann,
linux-leds, Marek Szyprowski, Conor Dooley, linux-media,
Michael Turquette, Ulf Hansson, Bartlomiej Zolnierkiewicz,
Seung-Woo Kim, Inki Dae, linux-arm-kernel, Sireesh Kodali,
Sylwester Nawrocki, linux-pm, Alina Yu
In-Reply-To: <20260623054842.21831-3-krzysztof.kozlowski@oss.qualcomm.com>
On Tue, 23 Jun 2026 07:48:43 +0200, Krzysztof Kozlowski wrote:
> There is no use of double colon '::' in YAML. OTOH, the literal style
> block, e.g. using '|' treats all characters as content [1] therefore
> single use of ':' in descriptions is perfectly fine, whenever '|' is
> used.
>
> Cleanup existing code, so the confusing style won't be re-used in new
> contributions.
>
> Link: https://yaml.org/spec/1.2.2/#literal-style [1]
> Acked-by: Alim Akhtar <alim.akhtar@samsung.com>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> ---
> I split the patches to avoid bounces from mailing list due to email size.
>
> This can go via clock tree (no dependencies)... or both could go via
> Rob's tree.
>
> Changes in v2:
> 1. Add tags (partial Reviews as Acks, as that's the meaning of Ack)
> ---
> .../devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-apq8064.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-apq8084.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-ipq6018.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-ipq8064.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-mdm9607.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-mdm9615.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-msm8660.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-msm8909.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-msm8916.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-msm8953.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-msm8974.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,gcc-sdm660.yaml | 2 +-
> Documentation/devicetree/bindings/clock/qcom,gpucc.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,ipq5018-gcc.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,ipq9574-gcc.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,qca8k-nsscc.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml | 2 +-
> Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,sm6115-lpasscc.yaml | 2 +-
> .../devicetree/bindings/clock/qcom,sm8350-videocc.yaml | 2 +-
> Documentation/devicetree/bindings/clock/qcom,videocc.yaml | 2 +-
> .../devicetree/bindings/clock/samsung,exynos5260-clock.yaml | 6 +++---
> .../devicetree/bindings/clock/samsung,exynos5410-clock.yaml | 2 +-
> .../devicetree/bindings/clock/samsung,exynos5433-clock.yaml | 2 +-
> .../devicetree/bindings/clock/samsung,exynos7-clock.yaml | 2 +-
> .../devicetree/bindings/clock/samsung,exynos850-clock.yaml | 2 +-
> .../bindings/clock/samsung,exynosautov9-clock.yaml | 2 +-
> .../bindings/clock/samsung,exynosautov920-clock.yaml | 2 +-
> .../devicetree/bindings/clock/samsung,s5pv210-clock.yaml | 2 +-
> 32 files changed, 34 insertions(+), 34 deletions(-)
>
Applied, thanks!
^ permalink raw reply
* Re: [PATCH v4 3/4] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC
From: Linus Walleij @ 2026-06-30 13:12 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: brgl, robh, krzk+dt, conor+dt, afaerber, mwalle,
andriy.shevchenko, tychang, linux-gpio, devicetree, linux-kernel,
linux-arm-kernel, linux-realtek-soc, cy.huang, stanley_chang,
james.tai
In-Reply-To: <20260622092335.1166876-4-eleanor.lin@realtek.com>
Hi Yu-Chun,
thanks for your patch!
On Mon, Jun 22, 2026 at 10:33 AM Yu-Chun Lin <eleanor.lin@realtek.com> wrote:
> From: Tzuyi Chang <tychang@realtek.com>
>
> Add support for the GPIO controller found on Realtek DHC RTD1625 SoCs.
>
> Unlike the existing Realtek GPIO driver (drivers/gpio/gpio-rtd.c),
> which manages pins via shared bank registers, the RTD1625 introduces
> a per-pin register architecture. Each GPIO line now has its own
> dedicated 32-bit control register to manage configuration independently,
> including direction, output value, input value, interrupt enable, and
> debounce. Therefore, this distinct hardware design requires a separate
> driver.
>
> Additionally, the RTD1625 GPIO controller has a specific hardware quirk:
> it fires both 'assert' and 'de-assert' interrupts simultaneously on any
> edge toggle. To handle this, we utilize the polarity register to route
> the requested edge (rising/falling) to the 'assert' IRQ line. The driver
> then filters out the unwanted 'de-assert' interrupt in the IRQ handler
> and pre-clears edge interrupts to prevent interrupt storms caused by
> unhandled dropped interrupts.
>
> Interrupt support is optional for this device, matching the dt-bindings.
> If the interrupts property is not provided, the driver simply skips IRQ
> initialization and operates purely as a basic GPIO controller.
>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> Signed-off-by: Tzuyi Chang <tychang@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
(...)
> +static void rtd1625_gpio_irq_handle(struct irq_desc *desc)
> +{
> + unsigned int (*get_reg_offset)(struct rtd1625_gpio *gpio, unsigned int offset);
> + struct rtd1625_gpio *data = irq_desc_get_handler_data(desc);
> + struct irq_domain *domain = data->gpio_chip.irq.domain;
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + unsigned int irq = irq_desc_get_irq(desc);
> + unsigned long status;
> + unsigned int reg_offset, i, j;
> + unsigned int girq;
So this
> + irq_hw_number_t hwirq;
> + u32 irq_type;
> +
> + if (irq == data->irqs[RTD1625_IRQ_ASSERT])
> + get_reg_offset = &rtd1625_gpio_gpa_offset;
> + else if (irq == data->irqs[RTD1625_IRQ_DEASSERT])
> + get_reg_offset = &rtd1625_gpio_gpda_offset;
> + else if (irq == data->irqs[2])
> + get_reg_offset = &rtd1625_gpio_level_offset;
> + else
> + return;
> +
> + chained_irq_enter(chip, desc);
> +
> + for (i = 0; i < data->info->num_gpios; i += 32) {
> + reg_offset = get_reg_offset(data, i);
> + status = readl_relaxed(data->irq_base + reg_offset);
> +
> + /*
> + * Hardware quirk: The controller fires both "assert" and "de-assert"
> + * interrupts simultaneously on any edge toggle.
> + * We must pre-clear edge interrupts here. If we drop an unwanted
> + * de-assert interrupt below, it will never reach the IRQ core
> + * (generic_handle_domain_irq), meaning ->irq_ack() won't be called.
> + * Failing to clear it here leads to an interrupt storm.
> + */
> + if (irq != data->irqs[RTD1625_IRQ_LEVEL])
> + writel_relaxed(status, data->irq_base + reg_offset);
> +
> + for_each_set_bit(j, &status, 32) {
> + hwirq = i + j;
> + girq = irq_find_mapping(domain, hwirq);
> + irq_type = irq_get_trigger_type(girq);
Just
irq_type = irq_get_trigger_type(irq_find_mapping(domain, hwirq));
Drop the intermediate variable.
> +static void rtd1625_gpio_ack_irq(struct irq_data *d)
> +{
> + struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
> + irq_hw_number_t hwirq = irqd_to_hwirq(d);
> + u32 irq_type = irqd_get_trigger_type(d);
> + u32 bit_mask = BIT(hwirq % 32);
This is a clear sign that your GPIOs and IRQs should be three-cell
(bank and offset) since they clearly have one each a separate
status bit in this register.
> +static void rtd1625_gpio_enable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
> +{
> + int gpda_reg_offset = rtd1625_gpio_gpda_offset(data, hwirq);
> + int gpa_reg_offset = rtd1625_gpio_gpa_offset(data, hwirq);
> + u32 clr_mask = BIT(hwirq % 32);
Same here.
> +static int rtd1625_gpio_setup_irq(struct platform_device *pdev, struct rtd1625_gpio *data)
> +{
> + struct gpio_irq_chip *irq_chip;
This is a super-confusing name for this variable.
It is called irq_chip but it's not struct irq_chip at all.
Call this girq like all other drivers.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v11 0/6] gpio: siul2-s32g2: add initial GPIO driver
From: Khristine Andreea Barbulescu @ 2026-06-30 12:58 UTC (permalink / raw)
To: Linus Walleij
Cc: Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chester Lin, Matthias Brugger, Ghennadi Procopciuc,
Larisa Grigore, Lee Jones, Shawn Guo, Sascha Hauer, Fabio Estevam,
Dong Aisheng, Jacky Bai, Greg Kroah-Hartman, Rafael J. Wysocki,
Srinivas Kandagatla, Alberto Ruiz, Christophe Lizzi, devicetree,
Enric Balletbo, Eric Chanudet, imx, linux-arm-kernel, linux-gpio,
linux-kernel, NXP S32 Linux Team, Pengutronix Kernel Team,
Vincent Guittot
In-Reply-To: <CAD++jL=S6vEgSW=V4gu4z=RtuvASNFUiofJb0X+fGYMqNQT7vQ@mail.gmail.com>
On 6/30/2026 2:50 PM, Linus Walleij wrote:
> On Wed, Jun 10, 2026 at 2:21 PM Khristine Andreea Barbulescu
> <khristineandreea.barbulescu@oss.nxp.com> wrote:
>
>> This patch series adds support for basic GPIO
>> operations using gpio-regmap.
>
> Sorry for my confused comment on jun 10, these patches all go to the
> pinctrl subsystem so I should merge them.
>
> Can you make a v12 based on v7.2-rc1 and I will apply them.
> Pick up ACKs!
>
> I will not apply the device tree patch, this will need to be queued
> in the SoC tree.
>
> Yours,
> Linus Walleij
Hi Linus,
v12 is now available. I've rebased the series on top of
v7.2-rc1 and collected the ACKs tags received in v11.
Best regards,
Khristine
^ permalink raw reply
* [PATCH v12 6/6] arm64: dts: s32g: describe GPIO and EIRQ resources in SIUL2 pinctrl node
From: Khristine Andreea Barbulescu @ 2026-06-30 12:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla
Cc: Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <20260630125403.546375-1-khristineandreea.barbulescu@oss.nxp.com>
Update the SIUL2 pinctrl node to describe the additional register
ranges and DT properties used by the updated SIUL2 driver.
Besides the MSCR and IMCR ranges used for pinmux and pin
configuration, the SIUL2 block also provides PGPDO and
PGPDI registers for GPIO output and input operations,
as well as an EIRQ register window for external interrupt configuration.
The driver supports both legacy pinctrl-only DTs and
extended DTs with GPIO and IRQ.
Reflect these resources in the SIUL2 pinctrl node by adding:
- the PGPDO and PGPDI register ranges
- the EIRQ register range
- gpio-controller, #gpio-cells and gpio-ranges
- interrupt-controller, #interrupt-cells and interrupts
Keep the hardware description aligned with the updated SIUL2
driver, where pinctrl, GPIO data access and the EIRQ register
block are described under the same device node.
Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
---
arch/arm64/boot/dts/freescale/s32g2.dtsi | 21 ++++++++++++++++++++-
arch/arm64/boot/dts/freescale/s32g3.dtsi | 21 ++++++++++++++++++++-
2 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/s32g2.dtsi b/arch/arm64/boot/dts/freescale/s32g2.dtsi
index 809019ea0e29..8dc0c5d9f368 100644
--- a/arch/arm64/boot/dts/freescale/s32g2.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g2.dtsi
@@ -135,7 +135,26 @@ pinctrl: pinctrl@4009c240 {
/* IMCR119-IMCR397 registers on siul2_1 */
<0x44010c1c 0x45c>,
/* IMCR430-IMCR495 registers on siul2_1 */
- <0x440110f8 0x108>;
+ <0x440110f8 0x108>,
+ /* PGPDO registers on siul2_0 */
+ <0x4009d700 0x10>,
+ /* PGPDI registers on siul2_0 */
+ <0x4009d740 0x10>,
+ /* PGPDO registers on siul2_1 */
+ <0x44011700 0x18>,
+ /* PGPDI registers on siul2_1 */
+ <0x44011740 0x18>,
+ /* EIRQ window: DISR0..IFEER0 */
+ <0x44010010 0x34>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 102>,
+ <&pinctrl 112 112 79>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>;
jtag_pins: jtag-pins {
jtag-grp0 {
diff --git a/arch/arm64/boot/dts/freescale/s32g3.dtsi b/arch/arm64/boot/dts/freescale/s32g3.dtsi
index 22e80fc03f9c..129d6ad8e5c6 100644
--- a/arch/arm64/boot/dts/freescale/s32g3.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g3.dtsi
@@ -193,7 +193,26 @@ pinctrl: pinctrl@4009c240 {
/* IMCR119-IMCR397 registers on siul2_1 */
<0x44010c1c 0x45c>,
/* IMCR430-IMCR495 registers on siul2_1 */
- <0x440110f8 0x108>;
+ <0x440110f8 0x108>,
+ /* PGPDO registers on siul2_0 */
+ <0x4009d700 0x10>,
+ /* PGPDI registers on siul2_0 */
+ <0x4009d740 0x10>,
+ /* PGPDO registers on siul2_1 */
+ <0x44011700 0x18>,
+ /* PGPDI registers on siul2_1 */
+ <0x44011740 0x18>,
+ /* EIRQ window: DISR0..IFEER0 */
+ <0x44010010 0x34>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 102>,
+ <&pinctrl 112 112 79>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>;
jtag_pins: jtag-pins {
jtag-grp0 {
--
2.34.1
^ permalink raw reply related
* [PATCH v12 5/6] pinctrl: s32cc: implement GPIO functionality
From: Khristine Andreea Barbulescu @ 2026-06-30 12:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla
Cc: Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <20260630125403.546375-1-khristineandreea.barbulescu@oss.nxp.com>
From: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
The updated SIUL2 block groups pinctrl, GPIO data access
and interrupt control within the same hardware unit.
The SIUL2 driver is therefore structured as a monolithic
pinctrl/GPIO driver.
GPIO data access and direction handling are implemented using the
gpio-regmap library backed by a virtual regmap. The virtual regmap
translates the gpio-regmap register model to the underlying SIUL2
registers: MSCR for direction, PGPDI for input values and PGPDO for
output values.
The existing pinctrl GPIO callbacks are used for the request/free path:
they switch the pad to GPIO mode on request and restore the previous
MSCR configuration when the GPIO is released.
This change came as a result of upstream review in the
following series:
https://lore.kernel.org/linux-gpio/20260120115923.3463866-4-khristineandreea.barbulescu@oss.nxp.com/T/#m543c9edbdde74bdc68b6a2364e8b975356c33043
https://lore.kernel.org/all/20260504131148.3622697-7-khristineandreea.barbulescu@oss.nxp.com/
Support both SIUL2 DT layouts:
- legacy pinctrl-only binding
- extended pinctrl/GPIO/irqchip binding
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
---
drivers/pinctrl/nxp/Kconfig | 3 +-
drivers/pinctrl/nxp/pinctrl-s32.h | 35 +-
drivers/pinctrl/nxp/pinctrl-s32cc.c | 701 +++++++++++++++++++++++++---
drivers/pinctrl/nxp/pinctrl-s32g2.c | 47 +-
4 files changed, 717 insertions(+), 69 deletions(-)
diff --git a/drivers/pinctrl/nxp/Kconfig b/drivers/pinctrl/nxp/Kconfig
index abca7ef97003..711c0fe11565 100644
--- a/drivers/pinctrl/nxp/Kconfig
+++ b/drivers/pinctrl/nxp/Kconfig
@@ -1,10 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
config PINCTRL_S32CC
bool
- depends on ARCH_S32 && OF
+ depends on ARCH_S32 && OF && GPIOLIB
select GENERIC_PINCTRL_GROUPS
select GENERIC_PINMUX_FUNCTIONS
select GENERIC_PINCONF
+ select GPIO_REGMAP
select REGMAP_MMIO
config PINCTRL_S32G2
diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h
index 8715befd5f05..028578a090e4 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32.h
+++ b/drivers/pinctrl/nxp/pinctrl-s32.h
@@ -2,7 +2,7 @@
*
* S32 pinmux core definitions
*
- * Copyright 2016-2020, 2022 NXP
+ * Copyright 2016-2020, 2022, 2026 NXP
* Copyright (C) 2022 SUSE LLC
* Copyright 2015-2016 Freescale Semiconductor, Inc.
* Copyright (C) 2012 Linaro Ltd.
@@ -34,11 +34,42 @@ struct s32_pin_range {
unsigned int end;
};
+/**
+ * struct s32_gpio_range - contiguous GPIO pin range within a SIUL2 module
+ * @gpio_base: first GPIO line offset in the GPIO range
+ * @pin_base: first pinctrl pin number mapped by this GPIO range
+ * @gpio_num: number of consecutive GPIO pins in the range
+ * @sparse: true if the PGPD layout is non-linear (resolved via pad map only);
+ * pins not found in the pad map are invalid for this range
+ */
+struct s32_gpio_range {
+ unsigned int gpio_base;
+ unsigned int pin_base;
+ unsigned int gpio_num;
+ bool sparse;
+};
+
+/**
+ * struct s32_gpio_pad_map - mapping between GPIO ranges and PGPD pads
+ * @gpio_start: first GPIO line offset in the range
+ * @gpio_end: last GPIO line offset in the range
+ * @pad: PGPD pad number serving the range
+ */
+struct s32_gpio_pad_map {
+ unsigned int gpio_start;
+ unsigned int gpio_end;
+ unsigned int pad;
+};
+
struct s32_pinctrl_soc_data {
const struct pinctrl_pin_desc *pins;
unsigned int npins;
const struct s32_pin_range *mem_pin_ranges;
unsigned int mem_regions;
+ const struct s32_gpio_range *gpio_ranges;
+ unsigned int num_gpio_ranges;
+ const struct s32_gpio_pad_map *gpio_pad_maps;
+ unsigned int num_gpio_pad_maps;
};
struct s32_pinctrl_soc_info {
@@ -53,6 +84,8 @@ struct s32_pinctrl_soc_info {
#define S32_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
#define S32_PIN_RANGE(_start, _end) { .start = _start, .end = _end }
+#define S32_GPIO_RANGE(gpio, pin, num) \
+ { .gpio_base = gpio, .pin_base = pin, .gpio_num = num }
int s32_pinctrl_probe(struct platform_device *pdev,
const struct s32_pinctrl_soc_data *soc_data);
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index b9b757e28bff..35e2f8a18ef2 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -2,7 +2,7 @@
/*
* Core driver for the S32 CC (Common Chassis) pin controller
*
- * Copyright 2017-2022,2024-2025 NXP
+ * Copyright 2017-2022,2024-2026 NXP
* Copyright (C) 2022 SUSE LLC
* Copyright 2015-2016 Freescale Semiconductor, Inc.
*/
@@ -10,6 +10,7 @@
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/regmap.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -39,6 +40,40 @@
#define S32_MSCR_ODE BIT(20)
#define S32_MSCR_OBE BIT(21)
+#define S32_GPIO_OP_SHIFT 16
+#define S32_GPIO_OP_MASK GENMASK(19, 16)
+
+#define S32_GPIO_OP_DIR 0 /* MSCR direction */
+#define S32_GPIO_OP_DAT BIT(S32_GPIO_OP_SHIFT) /* PGPDI read */
+#define S32_GPIO_OP_SET BIT(S32_GPIO_OP_SHIFT + 1) /* PGPDO write */
+
+/*
+ * [15:12] = GPIO bank / gpio range index
+ * [11:0] = real register offset or pin id
+ */
+#define S32_GPIO_BANK_SHIFT 12
+#define S32_GPIO_BANK_MASK GENMASK(15, 12)
+#define S32_GPIO_REG_MASK GENMASK(11, 0)
+
+#define S32_GPIO_ENCODE(bank, off) \
+ ((((bank) << S32_GPIO_BANK_SHIFT) & S32_GPIO_BANK_MASK) | \
+ ((off) & S32_GPIO_REG_MASK))
+
+#define S32_GPIO_DECODE_BANK(reg) \
+ (((reg) & S32_GPIO_BANK_MASK) >> S32_GPIO_BANK_SHIFT)
+
+#define S32_GPIO_DECODE_OFF(reg) \
+ ((reg) & S32_GPIO_REG_MASK)
+
+/*
+ * PGPDOs are 16bit registers that come in big endian
+ * order if they are grouped in pairs of two.
+ *
+ * For example, the order is PGPDO1, PGPDO0, PGPDO3, PGPDO2...
+ */
+#define S32_PGPD(N) (((N) ^ 1) * 2)
+#define S32_PGPD_SIZE 16
+
enum s32_write_type {
S32_PINCONF_UPDATE_ONLY,
S32_PINCONF_OVERWRITE,
@@ -72,6 +107,18 @@ struct s32_pinctrl_mem_region {
char name[8];
};
+/*
+ * struct s32_gpio_regmaps - GPIO register maps for a SIUL2 instance
+ * @pgpdo: regmap for Parallel GPIO Pad Data Out registers
+ * @pgpdi: regmap for Parallel GPIO Pad Data In registers
+ * @range: GPIO range info
+ */
+struct s32_gpio_regmaps {
+ struct regmap *pgpdo;
+ struct regmap *pgpdi;
+ const struct s32_gpio_range *range;
+};
+
/*
* struct gpio_pin_config - holds pin configuration for GPIO's
* @pin_id: Pin ID for this GPIO
@@ -98,6 +145,12 @@ struct s32_pinctrl_context {
* @pctl: a pointer to the pinctrl device structure
* @regions: reserved memory regions with start/end pin
* @info: structure containing information about the pin
+ * @gpio_regmaps: PGPDO/PGPDI regmaps for each SIUL2 module
+ * @num_gpio_regmaps: number of GPIO regmap entries
+ * @gpio_regmap: regmap bridging gpio-regmap to SIUL2 registers
+ * @gpio_rgm: gpio-regmap instance registered for this controller
+ * @ngpio: total number of GPIO line offsets
+ * @gpio_names: GPIO line names array passed to gpio-regmap
* @gpio_configs: saved configurations for GPIO pins
* @gpio_configs_lock: lock for the `gpio_configs` list
* @saved_context: configuration saved over system sleep
@@ -107,6 +160,12 @@ struct s32_pinctrl {
struct pinctrl_dev *pctl;
struct s32_pinctrl_mem_region *regions;
struct s32_pinctrl_soc_info *info;
+ struct s32_gpio_regmaps *gpio_regmaps;
+ unsigned int num_gpio_regmaps;
+ struct regmap *gpio_regmap;
+ struct gpio_regmap *gpio_rgm;
+ unsigned int ngpio;
+ const char *const *gpio_names;
struct list_head gpio_configs;
spinlock_t gpio_configs_lock;
#ifdef CONFIG_PM_SLEEP
@@ -356,88 +415,84 @@ static int s32_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
return info->nfunctions;
}
-static const char *s32_pmx_get_func_name(struct pinctrl_dev *pctldev,
- unsigned int selector)
-{
- struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct s32_pinctrl_soc_info *info = ipctl->info;
-
- return info->functions[selector].name;
-}
-
-static int s32_pmx_get_groups(struct pinctrl_dev *pctldev,
- unsigned int selector,
- const char * const **groups,
- unsigned int * const num_groups)
-{
- struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct s32_pinctrl_soc_info *info = ipctl->info;
-
- *groups = info->functions[selector].groups;
- *num_groups = info->functions[selector].ngroups;
-
- return 0;
-}
-
static int s32_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
- unsigned int offset)
+ unsigned int pin)
{
struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct gpio_pin_config *gpio_pin;
+ struct gpio_pin_config *gpio_pin __free(kfree) = NULL;
unsigned int config;
- unsigned long flags;
int ret;
- ret = s32_regmap_read(pctldev, offset, &config);
+ ret = s32_regmap_read(pctldev, pin, &config);
if (ret)
return ret;
- /* Save current configuration */
- gpio_pin = kmalloc_obj(*gpio_pin);
+ gpio_pin = kmalloc_obj(*gpio_pin, GFP_KERNEL);
if (!gpio_pin)
return -ENOMEM;
- gpio_pin->pin_id = offset;
+ gpio_pin->pin_id = pin;
gpio_pin->config = config;
- INIT_LIST_HEAD(&gpio_pin->list);
-
- spin_lock_irqsave(&ipctl->gpio_configs_lock, flags);
- list_add(&gpio_pin->list, &ipctl->gpio_configs);
- spin_unlock_irqrestore(&ipctl->gpio_configs_lock, flags);
/* GPIO pin means SSS = 0 */
- config &= ~S32_MSCR_SSS_MASK;
+ ret = s32_regmap_update(pctldev, pin,
+ S32_MSCR_SSS_MASK | S32_MSCR_IBE,
+ S32_MSCR_IBE);
+ if (ret)
+ return ret;
- return s32_regmap_write(pctldev, offset, config);
+ scoped_guard(spinlock_irqsave, &ipctl->gpio_configs_lock)
+ list_add(&no_free_ptr(gpio_pin)->list, &ipctl->gpio_configs);
+
+ return 0;
}
static void s32_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
- unsigned int offset)
+ unsigned int pin)
{
struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct gpio_pin_config *gpio_pin, *tmp;
+ struct gpio_pin_config *gpio_pin, *found = NULL;
unsigned long flags;
- int ret;
spin_lock_irqsave(&ipctl->gpio_configs_lock, flags);
-
- list_for_each_entry_safe(gpio_pin, tmp, &ipctl->gpio_configs, list) {
- if (gpio_pin->pin_id == offset) {
- ret = s32_regmap_write(pctldev, gpio_pin->pin_id,
- gpio_pin->config);
- if (ret != 0)
- goto unlock;
-
+ list_for_each_entry(gpio_pin, &ipctl->gpio_configs, list) {
+ if (gpio_pin->pin_id == pin) {
list_del(&gpio_pin->list);
- kfree(gpio_pin);
+ found = gpio_pin;
break;
}
}
-
-unlock:
spin_unlock_irqrestore(&ipctl->gpio_configs_lock, flags);
+
+ if (found) {
+ s32_regmap_write(pctldev, found->pin_id, found->config);
+ kfree(found);
+ }
+}
+
+static const char *s32_pmx_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct s32_pinctrl_soc_info *info = ipctl->info;
+
+ return info->functions[selector].name;
+}
+
+static int s32_pmx_get_groups(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ const char * const **groups,
+ unsigned int * const num_groups)
+{
+ struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct s32_pinctrl_soc_info *info = ipctl->info;
+
+ *groups = info->functions[selector].groups;
+ *num_groups = info->functions[selector].ngroups;
+
+ return 0;
}
static int s32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
@@ -649,9 +704,9 @@ static void s32_pinconf_dbg_show(struct pinctrl_dev *pctldev,
ret = s32_regmap_read(pctldev, pin_id, &config);
if (ret)
- return;
-
- seq_printf(s, "0x%x", config);
+ seq_printf(s, "error %d", ret);
+ else
+ seq_printf(s, "0x%x", config);
}
static void s32_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
@@ -669,8 +724,11 @@ static void s32_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
for (i = 0; i < grp->data.npins; i++) {
name = pin_get_name(pctldev, grp->data.pins[i]);
ret = s32_regmap_read(pctldev, grp->data.pins[i], &config);
- if (ret)
- return;
+ if (ret) {
+ seq_printf(s, "%s: error %d\n", name, ret);
+ continue;
+ }
+
seq_printf(s, "%s: 0x%x\n", name, config);
}
}
@@ -683,6 +741,477 @@ static const struct pinconf_ops s32_pinconf_ops = {
.pin_config_group_dbg_show = s32_pinconf_group_dbg_show,
};
+static void s32_gpio_free_saved_configs(void *data)
+{
+ struct s32_pinctrl *ipctl = data;
+ struct gpio_pin_config *gpio_pin, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipctl->gpio_configs_lock, flags);
+ list_for_each_entry_safe(gpio_pin, tmp, &ipctl->gpio_configs, list) {
+ list_del(&gpio_pin->list);
+ kfree(gpio_pin);
+ }
+ spin_unlock_irqrestore(&ipctl->gpio_configs_lock, flags);
+}
+
+static unsigned int s32_pin2pad(unsigned int pin)
+{
+ return pin / S32_PGPD_SIZE;
+}
+
+static u16 s32_pin2mask(unsigned int pin)
+{
+ /*
+ * From Reference manual :
+ * PGPDOx[PPDOy] = GPDO(x × 16) + (15 - y)[PDO_(x × 16) + (15 - y)]
+ */
+ return BIT(S32_PGPD_SIZE - 1 - pin % S32_PGPD_SIZE);
+}
+
+static int s32_gpio_get_range(struct s32_pinctrl *ipctl,
+ unsigned int gpio,
+ unsigned int *pin,
+ unsigned int *bank)
+{
+ const struct s32_pinctrl_soc_data *soc_data = ipctl->info->soc_data;
+ const struct s32_gpio_range *range;
+ int i;
+
+ for (i = 0; i < soc_data->num_gpio_ranges; i++) {
+ range = &soc_data->gpio_ranges[i];
+
+ if (gpio < range->gpio_base ||
+ gpio >= range->gpio_base + range->gpio_num)
+ continue;
+
+ if (pin)
+ *pin = range->pin_base + gpio - range->gpio_base;
+
+ if (bank)
+ *bank = i;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int s32_gpio_pad_map_xlate(struct s32_pinctrl *ipctl,
+ unsigned int gpio,
+ unsigned int *reg_offset,
+ u16 *mask)
+{
+ const struct s32_pinctrl_soc_data *soc_data = ipctl->info->soc_data;
+ const struct s32_gpio_pad_map *map;
+ unsigned int bit;
+ int i;
+
+ if (!soc_data->gpio_pad_maps || !soc_data->num_gpio_pad_maps)
+ return -EINVAL;
+
+ for (i = 0; i < soc_data->num_gpio_pad_maps; i++) {
+ map = &soc_data->gpio_pad_maps[i];
+
+ if (gpio < map->gpio_start || gpio > map->gpio_end)
+ continue;
+
+ bit = gpio - map->gpio_start;
+ *mask = BIT(S32_PGPD_SIZE - 1 - bit);
+ *reg_offset = S32_PGPD(map->pad);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static bool s32_gpio_pin_is_sparse(struct s32_pinctrl *ipctl, unsigned int pin)
+{
+ const struct s32_pinctrl_soc_data *soc_data = ipctl->info->soc_data;
+ const struct s32_gpio_range *range;
+ int i;
+
+ for (i = 0; i < soc_data->num_gpio_ranges; i++) {
+ range = &soc_data->gpio_ranges[i];
+ if (pin >= range->pin_base &&
+ pin < range->pin_base + range->gpio_num)
+ return range->sparse;
+ }
+
+ return false;
+}
+
+static int s32_gpio_xlate_pgpd(struct s32_pinctrl *ipctl,
+ unsigned int pin,
+ unsigned int *reg_offset,
+ u16 *mask)
+{
+ int ret;
+
+ /*
+ * Try the pad map first. For sparse ranges (SIUL2_1), only pins
+ * listed in the pad map are valid, return the error directly without
+ * falling back to the linear layout.
+ * For linear ranges (SIUL2_0), fall back to the linear pad-to-PGPD
+ * formula if no pad map entry matches.
+ */
+ ret = s32_gpio_pad_map_xlate(ipctl, pin, reg_offset, mask);
+ if (ret != -EINVAL)
+ return ret;
+
+ if (s32_gpio_pin_is_sparse(ipctl, pin))
+ return -EINVAL;
+
+ /* Linear layout fallback for non-sparse ranges. */
+ *mask = s32_pin2mask(pin);
+ *reg_offset = S32_PGPD(s32_pin2pad(pin));
+
+ return 0;
+}
+
+static int s32_gpio_reg_mask_xlate(struct gpio_regmap *gpio,
+ unsigned int base, unsigned int offset,
+ unsigned int *reg, unsigned int *mask)
+{
+ struct s32_pinctrl *ipctl = gpio_regmap_get_drvdata(gpio);
+ unsigned int pgpd_reg, pin, bank;
+ u16 pgpd_mask;
+ int ret;
+
+ ret = s32_gpio_get_range(ipctl, offset, &pin, &bank);
+ if (ret)
+ return ret;
+
+ switch (base) {
+ case S32_GPIO_OP_DIR:
+ /*
+ * Direction is controlled through MSCR OBE.
+ * Encode the real pin id in the virtual register.
+ */
+ *reg = S32_GPIO_OP_DIR | pin;
+ *mask = S32_MSCR_OBE;
+ return 0;
+
+ case S32_GPIO_OP_DAT:
+ case S32_GPIO_OP_SET:
+ ret = s32_gpio_xlate_pgpd(ipctl, pin, &pgpd_reg, &pgpd_mask);
+ if (ret)
+ return ret;
+ /*
+ * Encode both the GPIO bank and the real PGPD register offset.
+ */
+ *reg = base | S32_GPIO_ENCODE(bank, pgpd_reg);
+ *mask = pgpd_mask;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int s32_gpio_reg_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ struct s32_pinctrl *ipctl = context;
+ unsigned int op = reg & S32_GPIO_OP_MASK;
+ unsigned int vreg = reg & ~S32_GPIO_OP_MASK;
+ unsigned int bank;
+ unsigned int offset;
+ struct regmap *map;
+
+ switch (op) {
+ case S32_GPIO_OP_DIR:
+ /*
+ * Lower bits contain the real MSCR pin id.
+ */
+ offset = S32_GPIO_DECODE_OFF(vreg);
+
+ return s32_regmap_read(ipctl->pctl, offset, val);
+
+ case S32_GPIO_OP_DAT:
+ bank = S32_GPIO_DECODE_BANK(vreg);
+ offset = S32_GPIO_DECODE_OFF(vreg);
+
+ if (bank >= ipctl->num_gpio_regmaps)
+ return -EINVAL;
+
+ map = ipctl->gpio_regmaps[bank].pgpdi;
+ if (!map)
+ return -ENODEV;
+
+ return regmap_read(map, offset, val);
+
+ case S32_GPIO_OP_SET:
+ /*
+ * gpio-regmap uses update_bits() for set, so it needs to read
+ * the output register before writing the updated value.
+ */
+ bank = S32_GPIO_DECODE_BANK(vreg);
+ offset = S32_GPIO_DECODE_OFF(vreg);
+
+ if (bank >= ipctl->num_gpio_regmaps)
+ return -EINVAL;
+
+ map = ipctl->gpio_regmaps[bank].pgpdo;
+ if (!map)
+ return -ENODEV;
+
+ return regmap_read(map, offset, val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int s32_gpio_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ struct s32_pinctrl *ipctl = context;
+ unsigned int op = reg & S32_GPIO_OP_MASK;
+ unsigned int vreg = reg & ~S32_GPIO_OP_MASK;
+ unsigned int bank, offset, config;
+ struct regmap *map;
+
+ switch (op) {
+ case S32_GPIO_OP_DIR:
+ /*
+ * gpio-regmap sets S32_MSCR_OBE for output and clears it for
+ * input. Keep IBE enabled for GPIOs in both cases.
+ */
+ offset = S32_GPIO_DECODE_OFF(vreg);
+
+ config = S32_MSCR_IBE;
+ if (val & S32_MSCR_OBE)
+ config |= S32_MSCR_OBE;
+
+ return s32_regmap_update(ipctl->pctl, offset,
+ S32_MSCR_OBE | S32_MSCR_IBE,
+ config);
+
+ case S32_GPIO_OP_SET:
+ bank = S32_GPIO_DECODE_BANK(vreg);
+ offset = S32_GPIO_DECODE_OFF(vreg);
+
+ if (bank >= ipctl->num_gpio_regmaps)
+ return -EINVAL;
+
+ map = ipctl->gpio_regmaps[bank].pgpdo;
+ if (!map)
+ return -ENODEV;
+
+ return regmap_write(map, offset, val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct regmap_bus s32_gpio_regmap_bus = {
+ .reg_read = s32_gpio_reg_read,
+ .reg_write = s32_gpio_reg_write,
+};
+
+static const struct regmap_config s32_gpio_regmap_config = {
+ .name = "s32-gpio",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 1,
+ .max_register = S32_GPIO_OP_SET | S32_GPIO_BANK_MASK | S32_GPIO_REG_MASK,
+ .cache_type = REGCACHE_NONE,
+ .fast_io = true,
+};
+
+static int s32_gpio_get_ngpio(const struct s32_pinctrl_soc_data *soc_data,
+ unsigned int *ngpio)
+{
+ const struct s32_gpio_range *range;
+ unsigned int end, max = 0;
+ int i;
+
+ if (!soc_data->gpio_ranges || !soc_data->num_gpio_ranges)
+ return -EINVAL;
+
+ for (i = 0; i < soc_data->num_gpio_ranges; i++) {
+ range = &soc_data->gpio_ranges[i];
+
+ if (!range->gpio_num)
+ return -EINVAL;
+
+ end = range->gpio_base + range->gpio_num;
+
+ /*
+ * gpio_ranges must be ordered by gpio_base and must not overlap.
+ * The GPIO line space size is derived from the highest range end.
+ */
+ if (i > 0 && range->gpio_base < max)
+ return -EINVAL;
+
+ if (end > max)
+ max = end;
+ }
+
+ *ngpio = max;
+
+ return 0;
+}
+
+static int s32_init_gpio_regmap(struct platform_device *pdev,
+ struct s32_pinctrl *ipctl)
+{
+ ipctl->gpio_regmap =
+ devm_regmap_init(&pdev->dev, &s32_gpio_regmap_bus,
+ ipctl, &s32_gpio_regmap_config);
+ if (IS_ERR(ipctl->gpio_regmap))
+ return dev_err_probe(&pdev->dev,
+ PTR_ERR(ipctl->gpio_regmap),
+ "Failed to init GPIO regmap\n");
+
+ return 0;
+}
+
+static int s32_init_valid_mask(struct gpio_chip *chip, unsigned long *mask,
+ unsigned int ngpios)
+{
+ struct gpio_regmap *gpio = gpiochip_get_data(chip);
+ struct s32_pinctrl *ipctl = gpio_regmap_get_drvdata(gpio);
+ unsigned int gpio_num, pin, reg_offset;
+ u16 pgpd_mask;
+ int ret;
+
+ bitmap_zero(mask, ngpios);
+
+ for (gpio_num = 0; gpio_num < ngpios; gpio_num++) {
+ ret = s32_gpio_get_range(ipctl, gpio_num, &pin, NULL);
+ if (ret)
+ continue;
+
+ ret = s32_gpio_xlate_pgpd(ipctl, pin, ®_offset, &pgpd_mask);
+ if (ret)
+ continue;
+
+ bitmap_set(mask, gpio_num, 1);
+ }
+
+ return 0;
+}
+
+static int s32_gpio_populate_names(struct s32_pinctrl *ipctl)
+{
+ char **names;
+ unsigned int gpio;
+ unsigned int pin;
+ char port;
+ int ret;
+
+ names = devm_kcalloc(ipctl->dev, ipctl->ngpio, sizeof(*names),
+ GFP_KERNEL);
+ if (!names)
+ return -ENOMEM;
+
+ for (gpio = 0; gpio < ipctl->ngpio; gpio++) {
+ ret = s32_gpio_get_range(ipctl, gpio, &pin, NULL);
+ if (ret)
+ continue;
+
+ port = 'A' + pin / 16;
+
+ names[gpio] = devm_kasprintf(ipctl->dev, GFP_KERNEL,
+ "P%c_%02u", port, pin & 0xf);
+ if (!names[gpio])
+ return -ENOMEM;
+ }
+
+ ipctl->gpio_names = (const char *const *)names;
+
+ return 0;
+}
+
+static int s32_pinctrl_init_gpio_regmaps(struct platform_device *pdev,
+ struct s32_pinctrl *ipctl)
+{
+ const struct s32_pinctrl_soc_data *soc_data = ipctl->info->soc_data;
+ static const struct regmap_config pgpd_config = {
+ .reg_bits = 32,
+ .val_bits = 16,
+ .reg_stride = 2,
+ };
+ struct regmap_config cfg;
+ struct resource *res;
+ void __iomem *base;
+ unsigned int pgpdo_idx, pgpdi_idx;
+ unsigned int i;
+
+ if (!soc_data->gpio_ranges || !soc_data->num_gpio_ranges)
+ return 0;
+
+ ipctl->num_gpio_regmaps = soc_data->num_gpio_ranges;
+ ipctl->gpio_regmaps = devm_kcalloc(&pdev->dev, ipctl->num_gpio_regmaps,
+ sizeof(*ipctl->gpio_regmaps),
+ GFP_KERNEL);
+ if (!ipctl->gpio_regmaps)
+ return -ENOMEM;
+
+ for (i = 0; i < ipctl->num_gpio_regmaps; i++) {
+ ipctl->gpio_regmaps[i].range = &soc_data->gpio_ranges[i];
+
+ /*
+ * GPIO resources are placed after the pinctrl regions
+ */
+ pgpdo_idx = soc_data->mem_regions + i * 2;
+ pgpdi_idx = soc_data->mem_regions + i * 2 + 1;
+
+ /* PGPDO */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, pgpdo_idx);
+ if (!res)
+ return dev_err_probe(&pdev->dev, -ENOENT,
+ "Missing PGPDO resource %u\n", i);
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ cfg = pgpd_config;
+ cfg.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "pgpdo%u", i);
+ if (!cfg.name)
+ return -ENOMEM;
+
+ cfg.max_register = resource_size(res) - cfg.reg_stride;
+
+ ipctl->gpio_regmaps[i].pgpdo =
+ devm_regmap_init_mmio(&pdev->dev, base, &cfg);
+ if (IS_ERR(ipctl->gpio_regmaps[i].pgpdo))
+ return dev_err_probe(&pdev->dev,
+ PTR_ERR(ipctl->gpio_regmaps[i].pgpdo),
+ "Failed to init PGPDO regmap %u\n", i);
+
+ /* PGPDI */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, pgpdi_idx);
+ if (!res)
+ return dev_err_probe(&pdev->dev, -ENOENT,
+ "Missing PGPDI resource %u\n", i);
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ cfg = pgpd_config;
+ cfg.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "pgpdi%u", i);
+ if (!cfg.name)
+ return -ENOMEM;
+
+ cfg.max_register = resource_size(res) - cfg.reg_stride;
+
+ ipctl->gpio_regmaps[i].pgpdi =
+ devm_regmap_init_mmio(&pdev->dev, base, &cfg);
+ if (IS_ERR(ipctl->gpio_regmaps[i].pgpdi))
+ return dev_err_probe(&pdev->dev,
+ PTR_ERR(ipctl->gpio_regmaps[i].pgpdi),
+ "Failed to init PGPDI regmap %u\n", i);
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_PM_SLEEP
static bool s32_pinctrl_should_save(struct s32_pinctrl *ipctl,
unsigned int pin)
@@ -709,8 +1238,7 @@ int s32_pinctrl_suspend(struct device *dev)
const struct pinctrl_pin_desc *pin;
const struct s32_pinctrl_soc_info *info = ipctl->info;
struct s32_pinctrl_context *saved_context = &ipctl->saved_context;
- int i;
- int ret;
+ int i, ret;
unsigned int config;
for (i = 0; i < info->soc_data->npins; i++) {
@@ -721,7 +1249,7 @@ int s32_pinctrl_suspend(struct device *dev)
ret = s32_regmap_read(ipctl->pctl, pin->number, &config);
if (ret)
- return -EINVAL;
+ return ret;
saved_context->pads[i] = config;
}
@@ -736,7 +1264,7 @@ int s32_pinctrl_resume(struct device *dev)
const struct s32_pinctrl_soc_info *info = ipctl->info;
const struct pinctrl_pin_desc *pin;
struct s32_pinctrl_context *saved_context = &ipctl->saved_context;
- int ret, i;
+ int i, ret;
for (i = 0; i < info->soc_data->npins; i++) {
pin = &info->soc_data->pins[i];
@@ -745,7 +1273,7 @@ int s32_pinctrl_resume(struct device *dev)
continue;
ret = s32_regmap_write(ipctl->pctl, pin->number,
- saved_context->pads[i]);
+ saved_context->pads[i]);
if (ret)
return ret;
}
@@ -928,9 +1456,11 @@ int s32_pinctrl_probe(struct platform_device *pdev,
#ifdef CONFIG_PM_SLEEP
struct s32_pinctrl_context *saved_context;
#endif
+ struct gpio_regmap_config gpio_cfg = {};
struct pinctrl_desc *s32_pinctrl_desc;
struct s32_pinctrl_soc_info *info;
struct s32_pinctrl *ipctl;
+ unsigned int ngpio;
int ret;
if (!soc_data || !soc_data->pins || !soc_data->npins)
@@ -956,6 +1486,11 @@ int s32_pinctrl_probe(struct platform_device *pdev,
INIT_LIST_HEAD(&ipctl->gpio_configs);
spin_lock_init(&ipctl->gpio_configs_lock);
+ ret = devm_add_action_or_reset(&pdev->dev,
+ s32_gpio_free_saved_configs, ipctl);
+ if (ret)
+ return ret;
+
s32_pinctrl_desc =
devm_kzalloc(&pdev->dev, sizeof(*s32_pinctrl_desc), GFP_KERNEL);
if (!s32_pinctrl_desc)
@@ -974,6 +1509,11 @@ int s32_pinctrl_probe(struct platform_device *pdev,
return dev_err_probe(&pdev->dev, ret,
"Fail to probe dt properties\n");
+ ret = s32_pinctrl_init_gpio_regmaps(pdev, ipctl);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to init GPIO regmaps\n");
+
ret = devm_pinctrl_register_and_init(&pdev->dev, s32_pinctrl_desc,
ipctl, &ipctl->pctl);
if (ret)
@@ -995,7 +1535,42 @@ int s32_pinctrl_probe(struct platform_device *pdev,
return dev_err_probe(&pdev->dev, ret,
"Failed to enable pinctrl\n");
- dev_info(&pdev->dev, "Initialized S32 pinctrl driver\n");
+ /* Setup GPIO if GPIO ranges are defined */
+ if (!soc_data->gpio_ranges || !soc_data->num_gpio_ranges)
+ return 0;
+
+ ret = s32_gpio_get_ngpio(soc_data, &ngpio);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Invalid GPIO ranges\n");
+
+ ipctl->ngpio = ngpio;
+
+ ret = s32_gpio_populate_names(ipctl);
+ if (ret)
+ return ret;
+
+ ret = s32_init_gpio_regmap(pdev, ipctl);
+ if (ret)
+ return ret;
+
+ gpio_cfg.parent = &pdev->dev;
+ gpio_cfg.fwnode = dev_fwnode(&pdev->dev);
+ gpio_cfg.label = dev_name(&pdev->dev);
+ gpio_cfg.regmap = ipctl->gpio_regmap;
+ gpio_cfg.ngpio = ngpio;
+ gpio_cfg.names = ipctl->gpio_names;
+ gpio_cfg.reg_dir_out_base = GPIO_REGMAP_ADDR(S32_GPIO_OP_DIR);
+ gpio_cfg.reg_dat_base = GPIO_REGMAP_ADDR(S32_GPIO_OP_DAT);
+ gpio_cfg.reg_set_base = GPIO_REGMAP_ADDR(S32_GPIO_OP_SET);
+ gpio_cfg.reg_mask_xlate = s32_gpio_reg_mask_xlate;
+ gpio_cfg.init_valid_mask = s32_init_valid_mask;
+ gpio_cfg.drvdata = ipctl;
+
+ ipctl->gpio_rgm = devm_gpio_regmap_register(&pdev->dev, &gpio_cfg);
+ if (IS_ERR(ipctl->gpio_rgm))
+ return dev_err_probe(&pdev->dev,
+ PTR_ERR(ipctl->gpio_rgm),
+ "Unable to add gpio_regmap chip\n");
return 0;
}
diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c
index c49d28793b69..f9546c67a269 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32g2.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32g2.c
@@ -3,7 +3,7 @@
* NXP S32G pinctrl driver
*
* Copyright 2015-2016 Freescale Semiconductor, Inc.
- * Copyright 2017-2018, 2020-2022 NXP
+ * Copyright 2017-2018, 2020-2022, 2025-2026 NXP
* Copyright (C) 2022 SUSE LLC
*/
@@ -773,17 +773,48 @@ static const struct s32_pin_range s32_pin_ranges_siul2[] = {
S32_PIN_RANGE(942, 1007),
};
-static const struct s32_pinctrl_soc_data s32_pinctrl_data = {
+static const struct s32_gpio_range s32_gpio_ranges_siul2[] = {
+ S32_GPIO_RANGE(0, 0, 102),
+ /* SIUL2_1: sparse layout, PGPD mapping required for all pins */
+ { .gpio_base = 112, .pin_base = 112, .gpio_num = 79, .sparse = true },
+};
+
+/*
+ * SIUL2_1 GPIO ranges mapped to sparse PGPD pads.
+ *
+ * SIUL2_1 does not expose GPIO data registers as a linear pad
+ * sequence. Each entry describes a contiguous GPIO offset range
+ * and the PGPD pad servicing that range.
+ */
+static const struct s32_gpio_pad_map s32g_gpio_pad_maps[] = {
+ { 112, 122, 7 }, /* PH_00 .. PH_10 -> PGPD7 */
+ { 144, 159, 9 }, /* PJ_00 .. PJ_15 -> PGPD9 */
+ { 160, 175, 10 }, /* PK_00 .. PK_15 -> PGPD10 */
+ { 176, 190, 11 }, /* PL_00 .. PL_14 -> PGPD11 */
+};
+
+/* Legacy data for old DT bindings without GPIO support */
+static const struct s32_pinctrl_soc_data legacy_s32g_pinctrl_data = {
+ .pins = s32_pinctrl_pads_siul2,
+ .npins = ARRAY_SIZE(s32_pinctrl_pads_siul2),
+ .mem_pin_ranges = s32_pin_ranges_siul2,
+ .mem_regions = ARRAY_SIZE(s32_pin_ranges_siul2),
+};
+
+static const struct s32_pinctrl_soc_data s32g_pinctrl_data = {
.pins = s32_pinctrl_pads_siul2,
.npins = ARRAY_SIZE(s32_pinctrl_pads_siul2),
.mem_pin_ranges = s32_pin_ranges_siul2,
.mem_regions = ARRAY_SIZE(s32_pin_ranges_siul2),
+ .gpio_ranges = s32_gpio_ranges_siul2,
+ .num_gpio_ranges = ARRAY_SIZE(s32_gpio_ranges_siul2),
+ .gpio_pad_maps = s32g_gpio_pad_maps,
+ .num_gpio_pad_maps = ARRAY_SIZE(s32g_gpio_pad_maps),
};
static const struct of_device_id s32_pinctrl_of_match[] = {
{
.compatible = "nxp,s32g2-siul2-pinctrl",
- .data = &s32_pinctrl_data,
},
{ /* sentinel */ }
};
@@ -792,8 +823,16 @@ MODULE_DEVICE_TABLE(of, s32_pinctrl_of_match);
static int s32g_pinctrl_probe(struct platform_device *pdev)
{
const struct s32_pinctrl_soc_data *soc_data;
+ struct device_node *np = pdev->dev.of_node;
- soc_data = of_device_get_match_data(&pdev->dev);
+ /*
+ * Legacy DTs only describe the pinctrl resources.
+ * New DT changes extend the same node with GPIO resources.
+ */
+ if (of_property_present(np, "gpio-controller"))
+ soc_data = &s32g_pinctrl_data;
+ else
+ soc_data = &legacy_s32g_pinctrl_data;
return s32_pinctrl_probe(pdev, soc_data);
}
--
2.34.1
^ permalink raw reply related
* [PATCH v12 4/6] dt-bindings: pinctrl: s32g2-siul2: describe GPIO and EIRQ resources
From: Khristine Andreea Barbulescu @ 2026-06-30 12:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla
Cc: Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <20260630125403.546375-1-khristineandreea.barbulescu@oss.nxp.com>
Extend the S32G2 SIUL2 pinctrl binding to describe the GPIO data and
external interrupt resources present in the same SIUL2 hardware block.
Besides the MSCR and IMCR registers used for pin multiplexing and pad
configuration, SIUL2 also contains PGPDO and PGPDI registers
for GPIO data and EIRQ registers for external interrupt control.
Add GPIO controller properties because the SIUL2 block also provides
GPIO functionality, and gpio-ranges are needed to describe the
mapping between GPIO lines and pin controller pins.
Document the interrupt controller properties. The SIUL2 block
contains EIRQ hardware as part of the same register space. IRQ support
itself will be added in a follow-up patch series.
Update the example accordingly to show the complete SIUL2 register
layout, including the GPIO data and EIRQ register windows.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
---
.../pinctrl/nxp,s32g2-siul2-pinctrl.yaml | 90 +++++++++++++++++--
1 file changed, 84 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml
index a24286e4def6..36f2393fa406 100644
--- a/Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-# Copyright 2022 NXP
+# Copyright 2022, 2026 NXP
%YAML 1.2
---
$id: http://devicetree.org/schemas/pinctrl/nxp,s32g2-siul2-pinctrl.yaml#
@@ -17,8 +17,10 @@ description: |
SIUL2_0 @ 0x4009c000
SIUL2_1 @ 0x44010000
- Every SIUL2 region has multiple register types, and here only MSCR and
- IMCR registers need to be revealed for kernel to configure pinmux.
+ Every SIUL2 region has multiple register types. MSCR and IMCR registers
+ need to be revealed for kernel to configure pinmux. PGPDO and PGPDI
+ registers are used for GPIO output/input operations. EIRQ registers
+ are used for external interrupt configuration.
Please note that some register indexes are reserved in S32G2, such as
MSCR102-MSCR111, MSCR123-MSCR143, IMCR84-IMCR118 and IMCR398-IMCR429.
@@ -29,14 +31,22 @@ properties:
- nxp,s32g2-siul2-pinctrl
reg:
+ minItems: 6
description: |
- A list of MSCR/IMCR register regions to be reserved.
+ A list of MSCR/IMCR/PGPDO/PGPDI/EIRQ register regions to be reserved.
- MSCR (Multiplexed Signal Configuration Register)
An MSCR register can configure the associated pin as either a GPIO pin
or a function output pin depends on the selected signal source.
- IMCR (Input Multiplexed Signal Configuration Register)
An IMCR register can configure the associated pin as function input
pin depends on the selected signal source.
+ - PGPDO (Parallel GPIO Pad Data Out Register)
+ A PGPDO register is used to set the output value of a GPIO pin.
+ - PGPDI (Parallel GPIO Pad Data In Register)
+ A PGPDI register is used to read the input value of a GPIO pin.
+ - EIRQ (External Interrupt Request)
+ EIRQ registers are used to configure and manage external interrupts.
+
items:
- description: MSCR registers group 0 in SIUL2_0
- description: MSCR registers group 1 in SIUL2_1
@@ -44,6 +54,28 @@ properties:
- description: IMCR registers group 0 in SIUL2_0
- description: IMCR registers group 1 in SIUL2_1
- description: IMCR registers group 2 in SIUL2_1
+ - description: PGPDO registers in SIUL2_0
+ - description: PGPDI registers in SIUL2_0
+ - description: PGPDO registers in SIUL2_1
+ - description: PGPDI registers in SIUL2_1
+ - description: EIRQ registers in SIUL2_1
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+
+ gpio-ranges:
+ minItems: 1
+ maxItems: 4
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ interrupts:
+ maxItems: 1
patternProperties:
'-pins$':
@@ -86,11 +118,38 @@ required:
- compatible
- reg
+oneOf:
+ - description: Legacy pinctrl-only node
+ properties:
+ reg:
+ maxItems: 6
+
+ gpio-controller: false
+ "#gpio-cells": false
+ gpio-ranges: false
+ interrupt-controller: false
+ "#interrupt-cells": false
+ interrupts: false
+
+ - description: Pinctrl node with GPIO and external interrupt support
+ required:
+ - gpio-controller
+ - "#gpio-cells"
+ - gpio-ranges
+ - interrupt-controller
+ - "#interrupt-cells"
+ - interrupts
+ properties:
+ reg:
+ minItems: 11
+
additionalProperties: false
examples:
- |
- pinctrl@4009c240 {
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pinctrl: pinctrl@4009c240 {
compatible = "nxp,s32g2-siul2-pinctrl";
/* MSCR0-MSCR101 registers on siul2_0 */
@@ -104,7 +163,26 @@ examples:
/* IMCR119-IMCR397 registers on siul2_1 */
<0x44010c1c 0x45c>,
/* IMCR430-IMCR495 registers on siul2_1 */
- <0x440110f8 0x108>;
+ <0x440110f8 0x108>,
+ /* PGPDO registers on siul2_0 */
+ <0x4009d700 0x10>,
+ /* PGPDI registers on siul2_0 */
+ <0x4009d740 0x10>,
+ /* PGPDO registers on siul2_1 */
+ <0x44011700 0x18>,
+ /* PGPDI registers on siul2_1 */
+ <0x44011740 0x18>,
+ /* EIRQ registers on siul2_1 */
+ <0x44010010 0x34>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 102>,
+ <&pinctrl 112 112 79>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>;
llce-can0-pins {
llce-can0-grp0 {
--
2.34.1
^ permalink raw reply related
* [PATCH v12 3/6] pinctrl: s32cc: change to "devm_pinctrl_register_and_init"
From: Khristine Andreea Barbulescu @ 2026-06-30 12:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla
Cc: Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <20260630125403.546375-1-khristineandreea.barbulescu@oss.nxp.com>
From: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
Switch from "devm_pinctrl_register" to "devm_pinctrl_register_and_init"
and "pinctrl_enable" since this is the recommended way.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
---
drivers/pinctrl/nxp/pinctrl-s32cc.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index 8c5ec6a76a1f..b9b757e28bff 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -974,10 +974,10 @@ int s32_pinctrl_probe(struct platform_device *pdev,
return dev_err_probe(&pdev->dev, ret,
"Fail to probe dt properties\n");
- ipctl->pctl = devm_pinctrl_register(&pdev->dev, s32_pinctrl_desc,
- ipctl);
- if (IS_ERR(ipctl->pctl))
- return dev_err_probe(&pdev->dev, PTR_ERR(ipctl->pctl),
+ ret = devm_pinctrl_register_and_init(&pdev->dev, s32_pinctrl_desc,
+ ipctl, &ipctl->pctl);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
"Could not register s32 pinctrl driver\n");
#ifdef CONFIG_PM_SLEEP
@@ -990,7 +990,12 @@ int s32_pinctrl_probe(struct platform_device *pdev,
return -ENOMEM;
#endif
- dev_info(&pdev->dev, "initialized s32 pinctrl driver\n");
+ ret = pinctrl_enable(ipctl->pctl);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to enable pinctrl\n");
+
+ dev_info(&pdev->dev, "Initialized S32 pinctrl driver\n");
return 0;
}
--
2.34.1
^ permalink raw reply related
* [PATCH v12 0/6] gpio: siul2-s32g2: add initial GPIO driver
From: Khristine Andreea Barbulescu @ 2026-06-30 12:53 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla
Cc: Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
This patch series adds support for basic GPIO
operations using gpio-regmap.
There are two SIUL2 hardware modules: SIUL2_0 and SIUL2_1.
However, this driver exports both as a single GPIO driver.
This is because the interrupt registers are located only
in SIUL2_1, even for GPIOs that are part of SIUL2_0.
There are two gaps in the GPIO ranges:
- 102-111(inclusive) are invalid
- 123-143(inclusive) are invalid
Writing and reading GPIO values is done via the PGPDO/PGPDI
registers(Parallel GPIO Pad Data Output/Input) which are
16 bit registers, each bit corresponding to a GPIO.
Note that the PGPDO order is similar to a big-endian grouping
of two registers:
PGPDO1, PGPDO0, PGPDO3, PGPDO2, PGPDO5, PGPDO4, gap, PGPDO6.
v12 -> v11:
- rebase the series onto v7.2-rc1
- add Reviewed-by tags collected on v11
v11 -> v10:
- add GPIOLIB as explicit Kconfig dependency
- mark regmap config as fast_io to avoid mutex overhead
- propagate regmap errors in debug show callback and
suspend/resume paths instead of silently discarding them
- introduce a per-range sparse flag to handle SIUL2 instances
with a non-linear PGPD layout
- dt-bindings: drop redundant minItems from legacy oneOf branch,
add gpio-controller: false and related properties to prevent
GPIO/IRQ properties without the required reg entries and
drop maxItems from the GPIO+IRQ branch
v10 -> v9:
- implement GPIO via gpio-regmap backed by a regmap for
PGPDO/PGPDI register translation
- remove the successful probe message from the driver
- switch back to a single compatible string for both the
legacy and extended binding layout
- update binding: GPIO/IRQ properties required only
when extended reg layout is used
- remove unnecessary return value checks for MMIO
regmap operations
- replace kernel-doc style comments with regular comments
- solve relevant sashiko.dev findings
- rework GPIO request handling to preserve pinctrl ownership
- use __free(kfree) and no_free_ptr() in GPIO request path cleanup
v9 -> v8
- remove the SIUL2 syscon child nodes from the
device tree and DT bindings
- remove syscon child handling from the MFD
and pinctrl drivers
- remove the MFD driver and use a single monolithic
pinctrl/gpio/irqchip driver
- add a new compatible for the pinctrl+gpio binding
while keeping the previous compatible for the legacy
pinctrl-only binding
- update bindings to include the PGPDO/PGPDI and
IRQ register regions in the DT node for the
pinctrl/gpio/irq binding
- add IRQ-related entries in the bindings to
document the intended hierarchy; IRQ support
itself will be added in a future patch series
- update DT nodes to match the new hierarchy and
compatible scheme
- fix dtb warnings
- reorder commits: bug fixes, API changes, DT bindings,
driver implementation, DTS changes
- split commits further to separate minor
style-only adjustments
v8 -> v7
- remove all ': true' lines from properties in dt bindings
- remove NVMEM MFD cell from SIUL2 in dtsi
- remove NVMEM driver and configs
- expose SoC information via syscon cells SIUL2_0
and SIUL2_1 in MFD driver
- add SIUL2_0 and SIUL2_1 syscon nodes in dtsi
- add patternProperties for "^siul2_[0-1]$" for syscon nodes
- update example to include syscon cells with proper format
- remove `reg` property from pinctrl node in dt binding
- update Kconfig help text to reflect new syscon structure
instead of NVMEM for SoC information
- squash deprecated SIUL2 pinctrl binding with new MFD binding
- dropped "nxp,s32g3-siul2" from MFD driver match table
- fixed commit messages
- fixed dtb warnings
v7 -> v6
- fixed MAINTAINERS wrong file path
- add unevaluatedProperties, change siul2 node name, remove
jtag_pins label in the device tree schema
- change compatible definition in schema
- change node name in dtsi
- mentioned binding deprecation in commit messages
- split mfd cell conversion commit in two: one for the
previous refactoring, one for the mfd cell conversion
- removed Acked-by: Linus Walleij from commit:
"pinctrl: s32: convert the driver into an mfd cell"
because of changes to that commit
- deprecate the nxp,s32g2-siul2-pinctrl binding
- add NVMEM MFD cell for SIUL2
- made the GPIO driver not export invalid pins
(there are some gaps 102-111, 123-143)
- removed the need for gpio-reserved-ranges
- force initialized pinctrl_desc->num_custom_params to 0
v6 -> v5
- removed description for reg in the dt-bindings and added
maxItems
- dropped label for example in the dt-bindings
- simplified the example in the dt-bindings
- changed dt-bindings filename to nxp,s32g2-siul2.yaml
- changed title in the dt-bindings
- dropped minItmes from gpio-ranges/gpio-reserved-ranges
and added maxItems to gpio-reserved-ranges
- added required block for -grp[0-9]$ nodes
- switch to using "" as quotes
- kernel test robot: fixed frame sizes, added description
for reg_name, fixed typo in gpio_configs_lock, removed
uninitialized ret variable usage
- ordered includes in nxp-siul2.c, switched to dev-err-probe
added a mention that other commits will add nvmem functionality
to the mfd driver
- switched spin_lock_irqsave to scoped_guard statement
- switched dev_err to dev_err_probe in pinctrl-s32cc in places
reached during the probing part
v5 -> v4
- fixed di_div error
- fixed dt-bindings error
- added Co-developed-by tags
- added new MFD driver nxp-siul2.c
- made the old pinctrl driver an MFD cell
- added the GPIO driver in the existing SIUL2 pinctrl one
- Switch from "devm_pinctrl_register" to
"devm_pinctrl_register_and_init"
v4 -> v3
- removed useless parentheses
- added S32G3 fallback compatible
- fixed comment alignment
- fixed dt-bindings license
- fixed modpost: "__udivdi3"
- moved MAINTAINERS entry to have the new GPIO driver
together with other files related to S32G
v3 -> v2
- fix dt-bindings schema id
- add maxItems to gpio-ranges
- removed gpio label from dt-bindings example
- added changelog for the MAINTAINERS commit and
added separate entry for the SIUL2 GPIO driver
- added guard(raw_spinlock_irqsave) in
'siul2_gpio_set_direction'
- updated the description for
'devm_platform_get_and_ioremap_resource_byname'
v2 -> v1
dt-bindings:
- changed filename to match compatible
- fixed commit messages
- removed dt-bindings unnecessary properties descriptions
- added minItems for the interrupts property
driver:
- added depends on ARCH_S32 || COMPILE_TEST to Kconfig
- added select REGMAP_MMIO to Kconfig
- remove unnecessary include
- add of_node_put after `siul2_get_gpio_pinspec`
- removed inline from function definitions
- removed match data and moved the previous platdata
definition to the top of the file to be visible
- replace bitmap_set/clear with __clear_bit/set_bit
and devm_bitmap_zalloc with devm_kzalloc
- switched to gpiochip_generic_request/free/config
- fixed dev_err format for size_t reported by
kernel test robot
- add platform_get_and_ioremap_resource_byname wrapper
Andrei Stefanescu (2):
pinctrl: s32cc: change to "devm_pinctrl_register_and_init"
pinctrl: s32cc: implement GPIO functionality
Khristine Andreea Barbulescu (4):
pinctrl: s32cc: add/fix some comments
pinctrl: s32cc: remove inline specifiers
dt-bindings: pinctrl: s32g2-siul2: describe GPIO and EIRQ resources
arm64: dts: s32g: describe GPIO and EIRQ resources in SIUL2 pinctrl
node
.../pinctrl/nxp,s32g2-siul2-pinctrl.yaml | 90 ++-
arch/arm64/boot/dts/freescale/s32g2.dtsi | 21 +-
arch/arm64/boot/dts/freescale/s32g3.dtsi | 21 +-
drivers/pinctrl/nxp/Kconfig | 3 +-
drivers/pinctrl/nxp/pinctrl-s32.h | 35 +-
drivers/pinctrl/nxp/pinctrl-s32cc.c | 748 ++++++++++++++++--
drivers/pinctrl/nxp/pinctrl-s32g2.c | 47 +-
7 files changed, 871 insertions(+), 94 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH v12 2/6] pinctrl: s32cc: remove inline specifiers
From: Khristine Andreea Barbulescu @ 2026-06-30 12:53 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla
Cc: Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <20260630125403.546375-1-khristineandreea.barbulescu@oss.nxp.com>
Remove unnecessary inline specifiers from static functions.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
---
drivers/pinctrl/nxp/pinctrl-s32cc.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index 2a32df932d8a..8c5ec6a76a1f 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -131,13 +131,13 @@ s32_get_region(struct pinctrl_dev *pctldev, unsigned int pin)
return NULL;
}
-static inline int s32_check_pin(struct pinctrl_dev *pctldev,
- unsigned int pin)
+static int s32_check_pin(struct pinctrl_dev *pctldev,
+ unsigned int pin)
{
return s32_get_region(pctldev, pin) ? 0 : -EINVAL;
}
-static inline int s32_regmap_read(struct pinctrl_dev *pctldev,
+static int s32_regmap_read(struct pinctrl_dev *pctldev,
unsigned int pin, unsigned int *val)
{
struct s32_pinctrl_mem_region *region;
@@ -153,7 +153,7 @@ static inline int s32_regmap_read(struct pinctrl_dev *pctldev,
return regmap_read(region->map, offset, val);
}
-static inline int s32_regmap_write(struct pinctrl_dev *pctldev,
+static int s32_regmap_write(struct pinctrl_dev *pctldev,
unsigned int pin,
unsigned int val)
{
@@ -171,7 +171,7 @@ static inline int s32_regmap_write(struct pinctrl_dev *pctldev,
}
-static inline int s32_regmap_update(struct pinctrl_dev *pctldev, unsigned int pin,
+static int s32_regmap_update(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned int mask, unsigned int val)
{
struct s32_pinctrl_mem_region *region;
@@ -484,8 +484,8 @@ static int s32_get_slew_regval(int arg)
return -EINVAL;
}
-static inline void s32_pin_set_pull(enum pin_config_param param,
- unsigned int *mask, unsigned int *config)
+static void s32_pin_set_pull(enum pin_config_param param,
+ unsigned int *mask, unsigned int *config)
{
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
--
2.34.1
^ permalink raw reply related
* [PATCH v12 1/6] pinctrl: s32cc: add/fix some comments
From: Khristine Andreea Barbulescu @ 2026-06-30 12:53 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla
Cc: Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <20260630125403.546375-1-khristineandreea.barbulescu@oss.nxp.com>
Add/fix some comments and print statements.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
---
drivers/pinctrl/nxp/pinctrl-s32cc.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index 56be6e8d624e..2a32df932d8a 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -60,6 +60,12 @@ static u32 get_pin_func(u32 pinmux)
return pinmux & GENMASK(3, 0);
}
+/*
+ * struct s32_pinctrl_mem_region - memory region for a set of SIUL2 registers
+ * @map: regmap used for this range
+ * @pin_range: the pins controlled by these registers
+ * @name: name of the current range
+ */
struct s32_pinctrl_mem_region {
struct regmap *map;
const struct s32_pin_range *pin_range;
@@ -67,7 +73,7 @@ struct s32_pinctrl_mem_region {
};
/*
- * Holds pin configuration for GPIO's.
+ * struct gpio_pin_config - holds pin configuration for GPIO's
* @pin_id: Pin ID for this GPIO
* @config: Pin settings
* @list: Linked list entry for each gpio pin
@@ -79,20 +85,22 @@ struct gpio_pin_config {
};
/*
- * Pad config save/restore for power suspend/resume.
+ * struct s32_pinctrl_context - pad config save/restore for suspend/resume
+ * @pads: saved values for the pards
*/
struct s32_pinctrl_context {
unsigned int *pads;
};
/*
+ * struct s32_pinctrl - private driver data
* @dev: a pointer back to containing device
* @pctl: a pointer to the pinctrl device structure
* @regions: reserved memory regions with start/end pin
* @info: structure containing information about the pin
- * @gpio_configs: Saved configurations for GPIO pins
- * @gpiop_configs_lock: lock for the `gpio_configs` list
- * @s32_pinctrl_context: Configuration saved over system sleep
+ * @gpio_configs: saved configurations for GPIO pins
+ * @gpio_configs_lock: lock for the `gpio_configs` list
+ * @saved_context: configuration saved over system sleep
*/
struct s32_pinctrl {
struct device *dev;
@@ -970,7 +978,7 @@ int s32_pinctrl_probe(struct platform_device *pdev,
ipctl);
if (IS_ERR(ipctl->pctl))
return dev_err_probe(&pdev->dev, PTR_ERR(ipctl->pctl),
- "could not register s32 pinctrl driver\n");
+ "Could not register s32 pinctrl driver\n");
#ifdef CONFIG_PM_SLEEP
saved_context = &ipctl->saved_context;
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox