* [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver
@ 2026-05-04 12:41 Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 1/7] pinctrl: s32cc: use dev_err_probe() and improve error messages Khristine Andreea Barbulescu
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 12:41 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(set, get, direction_output/input, set_config).
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.
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 (5):
pinctrl: s32cc: use dev_err_probe() and improve error messages
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 | 107 ++-
arch/arm64/boot/dts/freescale/s32g2.dtsi | 26 +-
arch/arm64/boot/dts/freescale/s32g3.dtsi | 26 +-
drivers/pinctrl/nxp/pinctrl-s32.h | 15 +-
drivers/pinctrl/nxp/pinctrl-s32cc.c | 646 ++++++++++++++----
drivers/pinctrl/nxp/pinctrl-s32g2.c | 25 +-
6 files changed, 707 insertions(+), 138 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/7] pinctrl: s32cc: use dev_err_probe() and improve error messages
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
@ 2026-05-04 12:41 ` Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 2/7] pinctrl: s32cc: add/fix some comments Khristine Andreea Barbulescu
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 12:41 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
Change dev_err&return statements into dev_err_probe throughout the driver
on the probing path.
Signed-off-by: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
---
drivers/pinctrl/nxp/pinctrl-s32cc.c | 64 ++++++++++++++---------------
1 file changed, 30 insertions(+), 34 deletions(-)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index fe7cd641fddd..56be6e8d624e 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 NXP
+ * Copyright 2017-2022,2024-2025 NXP
* Copyright (C) 2022 SUSE LLC
* Copyright 2015-2016 Freescale Semiconductor, Inc.
*/
@@ -236,10 +236,10 @@ static int s32_dt_group_node_to_map(struct pinctrl_dev *pctldev,
}
ret = pinconf_generic_parse_dt_config(np, pctldev, &cfgs, &n_cfgs);
- if (ret) {
- dev_err(dev, "%pOF: could not parse node property\n", np);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "%pOF: could not parse node property\n",
+ np);
if (n_cfgs)
reserve++;
@@ -763,15 +763,15 @@ static int s32_pinctrl_parse_groups(struct device_node *np,
grp->data.name = np->name;
npins = of_property_count_elems_of_size(np, "pinmux", sizeof(u32));
- if (npins < 0) {
- dev_err(dev, "Failed to read 'pinmux' property in node %s.\n",
- grp->data.name);
- return -EINVAL;
- }
- if (!npins) {
- dev_err(dev, "The group %s has no pins.\n", grp->data.name);
- return -EINVAL;
- }
+ if (npins < 0)
+ return dev_err_probe(dev, -EINVAL,
+ "Failed to read 'pinmux' in node %s\n",
+ grp->data.name);
+
+ if (!npins)
+ return dev_err_probe(dev, -EINVAL,
+ "The group %s has no pins\n",
+ grp->data.name);
grp->data.npins = npins;
@@ -812,10 +812,9 @@ static int s32_pinctrl_parse_functions(struct device_node *np,
/* Initialise function */
func->name = np->name;
func->ngroups = of_get_child_count(np);
- if (func->ngroups == 0) {
- dev_err(info->dev, "no groups defined in %pOF\n", np);
- return -EINVAL;
- }
+ if (func->ngroups == 0)
+ return dev_err_probe(info->dev, -EINVAL,
+ "No groups defined in %pOF\n", np);
groups = devm_kcalloc(info->dev, func->ngroups,
sizeof(*func->groups), GFP_KERNEL);
@@ -886,10 +885,9 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
}
nfuncs = of_get_child_count(np);
- if (nfuncs <= 0) {
- dev_err(&pdev->dev, "no functions defined\n");
- return -EINVAL;
- }
+ if (nfuncs <= 0)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "No functions defined\n");
info->nfunctions = nfuncs;
info->functions = devm_kcalloc(&pdev->dev, nfuncs,
@@ -919,18 +917,17 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
int s32_pinctrl_probe(struct platform_device *pdev,
const struct s32_pinctrl_soc_data *soc_data)
{
- struct s32_pinctrl *ipctl;
- int ret;
- struct pinctrl_desc *s32_pinctrl_desc;
- struct s32_pinctrl_soc_info *info;
#ifdef CONFIG_PM_SLEEP
struct s32_pinctrl_context *saved_context;
#endif
+ struct pinctrl_desc *s32_pinctrl_desc;
+ struct s32_pinctrl_soc_info *info;
+ struct s32_pinctrl *ipctl;
+ int ret;
- if (!soc_data || !soc_data->pins || !soc_data->npins) {
- dev_err(&pdev->dev, "wrong pinctrl info\n");
- return -EINVAL;
- }
+ if (!soc_data || !soc_data->pins || !soc_data->npins)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "Wrong pinctrl info\n");
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
@@ -965,10 +962,9 @@ int s32_pinctrl_probe(struct platform_device *pdev,
s32_pinctrl_desc->owner = THIS_MODULE;
ret = s32_pinctrl_probe_dt(pdev, ipctl);
- if (ret) {
- dev_err(&pdev->dev, "fail to probe dt properties\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Fail to probe dt properties\n");
ipctl->pctl = devm_pinctrl_register(&pdev->dev, s32_pinctrl_desc,
ipctl);
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/7] pinctrl: s32cc: add/fix some comments
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 1/7] pinctrl: s32cc: use dev_err_probe() and improve error messages Khristine Andreea Barbulescu
@ 2026-05-04 12:41 ` Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 3/7] pinctrl: s32cc: remove inline specifiers Khristine Andreea Barbulescu
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 12:41 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
Add/fix some comments and print
statements.
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 | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index 56be6e8d624e..558d9ae1fa0c 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -60,14 +60,20 @@ 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;
char name[8];
};
-/*
- * 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
@@ -78,21 +84,23 @@ struct gpio_pin_config {
struct list_head list;
};
-/*
- * 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;
@@ -321,7 +329,7 @@ static int s32_pmx_set(struct pinctrl_dev *pctldev, unsigned int selector,
/* Check beforehand so we don't have a partial config. */
for (i = 0; i < grp->data.npins; i++) {
if (s32_check_pin(pctldev, grp->data.pins[i]) != 0) {
- dev_err(info->dev, "invalid pin: %u in group: %u\n",
+ dev_err(info->dev, "Invalid pin: %u in group: %u\n",
grp->data.pins[i], group);
return -EINVAL;
}
@@ -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 [flat|nested] 9+ messages in thread
* [PATCH 3/7] pinctrl: s32cc: remove inline specifiers
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 1/7] pinctrl: s32cc: use dev_err_probe() and improve error messages Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 2/7] pinctrl: s32cc: add/fix some comments Khristine Andreea Barbulescu
@ 2026-05-04 12:41 ` Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 4/7] pinctrl: s32cc: change to "devm_pinctrl_register_and_init" Khristine Andreea Barbulescu
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 12:41 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
Remove unnecessary inline specifiers from
static functions.
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 558d9ae1fa0c..1c95e0022020 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 [flat|nested] 9+ messages in thread
* [PATCH 4/7] pinctrl: s32cc: change to "devm_pinctrl_register_and_init"
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
` (2 preceding siblings ...)
2026-05-04 12:41 ` [PATCH 3/7] pinctrl: s32cc: remove inline specifiers Khristine Andreea Barbulescu
@ 2026-05-04 12:41 ` Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 5/7] dt-bindings: pinctrl: s32g2-siul2: describe GPIO and EIRQ resources Khristine Andreea Barbulescu
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 12:41 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
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: 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>
---
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 1c95e0022020..27757f2c5570 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 [flat|nested] 9+ messages in thread
* [PATCH 5/7] dt-bindings: pinctrl: s32g2-siul2: describe GPIO and EIRQ resources
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
` (3 preceding siblings ...)
2026-05-04 12:41 ` [PATCH 4/7] pinctrl: s32cc: change to "devm_pinctrl_register_and_init" Khristine Andreea Barbulescu
@ 2026-05-04 12:41 ` Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 6/7] pinctrl: s32cc: implement GPIO functionality Khristine Andreea Barbulescu
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 12:41 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
Extend the S32G2 SIUL2 pinctrl binding to describe the additional
resources used by the updated SIUL2 pinctrl driver.
Besides the MSCR and IMCR register ranges used for pinmux and
pin configuration, the SIUL2 block also contains PGPDO and PGPDI
registers for GPIO output and input operations, as well as EIRQ
registers used for external interrupt configuration.
Add GPIO controller properties:
- gpio-controller
- #gpio-cells
- gpio-ranges
Add interrupt controller properties:
- interrupt-controller
- #interrupt-cells
- interrupts
Also update the binding example to show the complete SIUL2 register
layout, including the GPIO data and EIRQ register windows.
Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
---
.../pinctrl/nxp,s32g2-siul2-pinctrl.yaml | 107 ++++++++++++++++--
1 file changed, 98 insertions(+), 9 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..0bd341f1e84d 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,26 +17,39 @@ 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.
properties:
compatible:
- enum:
- - nxp,s32g2-siul2-pinctrl
+ oneOf:
+ - const: nxp,s32g2-siul2-pinctrl
+ - items:
+ - const: nxp,s32g2-siul2-pinctrl-gpio
+ - const: nxp,s32g2-siul2-pinctrl
reg:
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.
+
+ minItems: 6
items:
- description: MSCR registers group 0 in SIUL2_0
- description: MSCR registers group 1 in SIUL2_1
@@ -44,6 +57,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$':
@@ -82,6 +117,38 @@ patternProperties:
additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nxp,s32g2-siul2-pinctrl-gpio
+ then:
+ properties:
+ reg:
+ minItems: 11
+ maxItems: 11
+
+ required:
+ - gpio-controller
+ - "#gpio-cells"
+ - gpio-ranges
+ - interrupt-controller
+ - "#interrupt-cells"
+ - interrupts
+
+ else:
+ properties:
+ reg:
+ minItems: 6
+ maxItems: 6
+ gpio-controller: false
+ "#gpio-cells": false
+ gpio-ranges: false
+ interrupt-controller: false
+ "#interrupt-cells": false
+ interrupts: false
+
required:
- compatible
- reg
@@ -90,8 +157,11 @@ additionalProperties: false
examples:
- |
- pinctrl@4009c240 {
- compatible = "nxp,s32g2-siul2-pinctrl";
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pinctrl: pinctrl@4009c240 {
+ compatible = "nxp,s32g2-siul2-pinctrl-gpio",
+ "nxp,s32g2-siul2-pinctrl";
/* MSCR0-MSCR101 registers on siul2_0 */
reg = <0x4009c240 0x198>,
@@ -104,7 +174,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 102 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 [flat|nested] 9+ messages in thread
* [PATCH 6/7] pinctrl: s32cc: implement GPIO functionality
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
` (4 preceding siblings ...)
2026-05-04 12:41 ` [PATCH 5/7] dt-bindings: pinctrl: s32g2-siul2: describe GPIO and EIRQ resources Khristine Andreea Barbulescu
@ 2026-05-04 12:41 ` Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 7/7] arm64: dts: s32g: describe GPIO and EIRQ resources in SIUL2 pinctrl node Khristine Andreea Barbulescu
2026-05-04 13:14 ` [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
7 siblings, 0 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 12:41 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
From: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
Add basic GPIO functionality (request, free, get, set) for
the existing pinctrl SIUL2 driver since the hardware for
pinctrl&GPIO is tightly coupled.
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.
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
Support both SIUL2 DT layouts:
- legacy pinctrl-only binding
- extended pinctrl/GPIO/irqchip binding
Also, remove pinmux_ops which are no longer needed.
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-s32.h | 15 +-
drivers/pinctrl/nxp/pinctrl-s32cc.c | 527 ++++++++++++++++++++++++----
drivers/pinctrl/nxp/pinctrl-s32g2.c | 25 +-
3 files changed, 499 insertions(+), 68 deletions(-)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h
index 8715befd5f05..d33f4d631dd6 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,23 @@ struct s32_pin_range {
unsigned int end;
};
+/**
+ * struct s32_gpio_range - contiguous GPIO pin range within a SIUL2 module
+ * @gpio_base: first pinctrl pin number in the GPIO range
+ * @gpio_num: number of consecutive GPIO pins in the range
+ */
+struct s32_gpio_range {
+ unsigned int gpio_base;
+ unsigned int gpio_num;
+};
+
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;
};
struct s32_pinctrl_soc_info {
@@ -53,6 +65,7 @@ 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(_base, _num) { .gpio_base = _base, .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 27757f2c5570..2d9b14792cf4 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.
*/
@@ -39,6 +39,14 @@
#define S32_MSCR_ODE BIT(20)
#define S32_MSCR_OBE BIT(21)
+/* 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 +80,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
@@ -96,8 +116,11 @@ struct s32_pinctrl_context {
* struct s32_pinctrl - private driver data
* @dev: a pointer back to containing device
* @pctl: a pointer to the pinctrl device structure
+ * @gc: a pointer to the gpio_chip
* @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_configs: saved configurations for GPIO pins
* @gpio_configs_lock: lock for the `gpio_configs` list
* @saved_context: configuration saved over system sleep
@@ -105,8 +128,11 @@ struct s32_pinctrl_context {
struct s32_pinctrl {
struct device *dev;
struct pinctrl_dev *pctl;
+ struct gpio_chip gc;
struct s32_pinctrl_mem_region *regions;
struct s32_pinctrl_soc_info *info;
+ struct s32_gpio_regmaps *gpio_regmaps;
+ unsigned int num_gpio_regmaps;
struct list_head gpio_configs;
spinlock_t gpio_configs_lock;
#ifdef CONFIG_PM_SLEEP
@@ -379,67 +405,6 @@ static int s32_pmx_get_groups(struct pinctrl_dev *pctldev,
return 0;
}
-static int s32_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range,
- unsigned int offset)
-{
- struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct gpio_pin_config *gpio_pin;
- unsigned int config;
- unsigned long flags;
- int ret;
-
- ret = s32_regmap_read(pctldev, offset, &config);
- if (ret)
- return ret;
-
- /* Save current configuration */
- gpio_pin = kmalloc_obj(*gpio_pin);
- if (!gpio_pin)
- return -ENOMEM;
-
- gpio_pin->pin_id = offset;
- 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;
-
- return s32_regmap_write(pctldev, offset, config);
-}
-
-static void s32_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range,
- unsigned int offset)
-{
- struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct gpio_pin_config *gpio_pin, *tmp;
- 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_del(&gpio_pin->list);
- kfree(gpio_pin);
- break;
- }
- }
-
-unlock:
- spin_unlock_irqrestore(&ipctl->gpio_configs_lock, flags);
-}
-
static int s32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int offset,
@@ -463,8 +428,6 @@ static const struct pinmux_ops s32_pmx_ops = {
.get_function_name = s32_pmx_get_func_name,
.get_function_groups = s32_pmx_get_groups,
.set_mux = s32_pmx_set,
- .gpio_request_enable = s32_pmx_gpio_request_enable,
- .gpio_disable_free = s32_pmx_gpio_disable_free,
.gpio_set_direction = s32_pmx_gpio_set_direction,
};
@@ -683,6 +646,397 @@ static const struct pinconf_ops s32_pinconf_ops = {
.pin_config_group_dbg_show = s32_pinconf_group_dbg_show,
};
+static struct s32_pinctrl *to_s32_pinctrl(struct gpio_chip *chip)
+{
+ return container_of(chip, struct s32_pinctrl, gc);
+}
+
+static struct regmap *s32_gpio_get_pgpd_regmap(struct gpio_chip *chip,
+ unsigned int gpio,
+ bool output,
+ unsigned int *relative_pin)
+{
+ struct s32_pinctrl *ipctl = to_s32_pinctrl(chip);
+ const struct s32_gpio_range *range;
+ int i;
+
+ for (i = 0; i < ipctl->num_gpio_regmaps; i++) {
+ range = ipctl->gpio_regmaps[i].range;
+ if (gpio >= range->gpio_base &&
+ gpio < range->gpio_base + range->gpio_num) {
+ if (relative_pin)
+ *relative_pin = gpio - range->gpio_base;
+ return output ? ipctl->gpio_regmaps[i].pgpdo :
+ ipctl->gpio_regmaps[i].pgpdi;
+ }
+ }
+
+ return NULL;
+}
+
+static int s32_gpio_request(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct s32_pinctrl *ipctl = to_s32_pinctrl(gc);
+ struct pinctrl_dev *pctldev = ipctl->pctl;
+ struct gpio_pin_config *gpio_pin;
+ unsigned int config;
+ int ret;
+
+ ret = s32_regmap_read(pctldev, gpio, &config);
+ if (ret)
+ return ret;
+
+ /* Save current configuration */
+ gpio_pin = kmalloc(sizeof(*gpio_pin), GFP_KERNEL);
+ if (!gpio_pin)
+ return -ENOMEM;
+
+ gpio_pin->pin_id = gpio;
+ gpio_pin->config = config;
+ INIT_LIST_HEAD(&gpio_pin->list);
+
+ /* GPIO pin means SSS = 0 */
+ config &= ~S32_MSCR_SSS_MASK;
+
+ ret = s32_regmap_write(pctldev, gpio, config);
+ if (ret) {
+ kfree(gpio_pin);
+ return ret;
+ }
+
+ scoped_guard(spinlock_irqsave, &ipctl->gpio_configs_lock)
+ list_add(&gpio_pin->list, &ipctl->gpio_configs);
+
+ return 0;
+}
+
+static void s32_gpio_free(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct s32_pinctrl *ipctl = to_s32_pinctrl(gc);
+ struct pinctrl_dev *pctldev = ipctl->pctl;
+ struct gpio_pin_config *gpio_pin, *tmp;
+ int ret;
+
+ guard(spinlock_irqsave)(&ipctl->gpio_configs_lock);
+
+ list_for_each_entry_safe(gpio_pin, tmp, &ipctl->gpio_configs, list) {
+ if (gpio_pin->pin_id == gpio) {
+ list_del(&gpio_pin->list);
+ ret = s32_regmap_write(pctldev, gpio_pin->pin_id,
+ gpio_pin->config);
+ if (ret)
+ dev_warn(gc->parent, "Failed to restore config for pin %u\n", gpio);
+ kfree(gpio_pin);
+ return;
+ }
+ }
+}
+
+static int s32_gpio_get_dir(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct s32_pinctrl *ipctl = to_s32_pinctrl(chip);
+ unsigned int reg_value;
+ int ret;
+
+ ret = s32_regmap_read(ipctl->pctl, gpio, ®_value);
+ if (ret)
+ return ret;
+
+ if (!(reg_value & S32_MSCR_IBE))
+ return -EIO;
+
+ return reg_value & S32_MSCR_OBE ? GPIO_LINE_DIRECTION_OUT :
+ GPIO_LINE_DIRECTION_IN;
+}
+
+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 struct regmap *s32_gpio_get_regmap_offset_mask(struct gpio_chip *chip,
+ unsigned int gpio,
+ unsigned int *reg_offset,
+ u16 *mask,
+ bool output)
+{
+ struct regmap *regmap;
+ unsigned int pad, relative_pin;
+
+ regmap = s32_gpio_get_pgpd_regmap(chip, gpio, output, &relative_pin);
+ if (!regmap)
+ return NULL;
+
+ *mask = s32_pin2mask(relative_pin);
+ pad = s32_pin2pad(relative_pin);
+
+ *reg_offset = S32_PGPD(pad);
+
+ return regmap;
+}
+
+static int s32_gpio_set_val(struct gpio_chip *chip, unsigned int gpio,
+ int value)
+{
+ unsigned int reg_offset;
+ struct regmap *regmap;
+ u16 mask;
+
+ regmap = s32_gpio_get_regmap_offset_mask(chip, gpio, ®_offset,
+ &mask, true);
+ if (!regmap)
+ return -ENODEV;
+
+ value = value ? mask : 0;
+
+ return regmap_update_bits(regmap, reg_offset, mask, value);
+}
+
+static int s32_gpio_set(struct gpio_chip *chip, unsigned int gpio,
+ int value)
+{
+ return s32_gpio_set_val(chip, gpio, value);
+}
+
+static int s32_gpio_get(struct gpio_chip *chip, unsigned int gpio)
+{
+ unsigned int reg_offset, value;
+ struct regmap *regmap;
+ u16 mask;
+ int ret;
+
+ regmap = s32_gpio_get_regmap_offset_mask(chip, gpio, ®_offset,
+ &mask, false);
+ if (!regmap)
+ return -EINVAL;
+
+ ret = regmap_read(regmap, reg_offset, &value);
+ if (ret)
+ return ret;
+
+ return !!(value & mask);
+}
+
+static int s32_gpio_dir_out(struct gpio_chip *chip, unsigned int gpio,
+ int val)
+{
+ struct s32_pinctrl *ipctl = to_s32_pinctrl(chip);
+ int ret;
+
+ ret = s32_gpio_set_val(chip, gpio, val);
+ if (ret)
+ return ret;
+
+ return s32_pmx_gpio_set_direction(ipctl->pctl, NULL, gpio, false);
+}
+
+static int s32_gpio_dir_in(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct s32_pinctrl *ipctl = to_s32_pinctrl(chip);
+
+ return s32_pmx_gpio_set_direction(ipctl->pctl, NULL, gpio, true);
+}
+
+static bool s32_gpio_is_valid(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct s32_pinctrl *ipctl = to_s32_pinctrl(chip);
+ const struct s32_pinctrl_soc_data *soc_data;
+ const struct pinctrl_pin_desc *pins;
+ int i;
+
+ soc_data = ipctl->info->soc_data;
+ pins = ipctl->info->soc_data->pins;
+ for (i = 0; i < soc_data->npins && pins[i].number <= gpio; i++)
+ if (pins[i].number == gpio)
+ return true;
+
+ return false;
+}
+
+static int s32_init_valid_mask(struct gpio_chip *chip, unsigned long *mask,
+ unsigned int ngpios)
+{
+ struct s32_pinctrl *ipctl = to_s32_pinctrl(chip);
+ const struct s32_pinctrl_soc_data *soc_data;
+ const struct pinctrl_pin_desc *pins;
+ int i;
+
+ bitmap_zero(mask, ngpios);
+
+ soc_data = ipctl->info->soc_data;
+ pins = soc_data->pins;
+
+ for (i = 0; i < soc_data->npins; i++)
+ if (pins[i].number < ngpios)
+ bitmap_set(mask, pins[i].number, 1);
+
+ return 0;
+}
+
+static int s32_gpio_gen_names(struct device *dev, struct gpio_chip *gc,
+ unsigned int cnt, char **names, char *ch_index,
+ unsigned int *num_index)
+{
+ unsigned int gpio;
+ unsigned int i;
+
+ /*
+ * GPIO names follow the format P<port>_<pin>, for example:
+ * PA_00 .. PA_15, PB_00 .. PB_15, ..
+ *
+ * @num_index tracks the absolute GPIO index. The port letter is
+ * advanced whenever the index crosses a 16-pin boundary.
+ */
+ for (i = 0; i < cnt; i++) {
+ gpio = *num_index;
+ if (i != 0 && (gpio % 16) == 0)
+ (*ch_index)++;
+
+ if (s32_gpio_is_valid(gc, gpio)) {
+ names[i] = devm_kasprintf(dev, GFP_KERNEL, "P%c_%02d",
+ *ch_index, gpio & 0xF);
+ if (!names[i])
+ return -ENOMEM;
+ }
+
+ (*num_index)++;
+ }
+
+ return 0;
+}
+
+static int s32_gpio_populate_names(struct device *dev,
+ struct s32_pinctrl *ipctl)
+{
+ const struct s32_pinctrl_soc_data *soc_data = ipctl->info->soc_data;
+ const struct s32_gpio_range *range;
+ unsigned int num_index = 0;
+ char ch_index = 'A';
+ char **names;
+ int i, ret;
+
+ names = devm_kcalloc(dev, ipctl->gc.ngpio, sizeof(*names),
+ GFP_KERNEL);
+ if (!names)
+ return -ENOMEM;
+
+ for (i = 0; i < soc_data->num_gpio_ranges; i++) {
+ range = &soc_data->gpio_ranges[i];
+
+ if (range->gpio_base % 16 == 0)
+ num_index = 0;
+
+ ret = s32_gpio_gen_names(dev, &ipctl->gc, range->gpio_num,
+ names + range->gpio_base,
+ &ch_index, &num_index);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Error setting SIUL2_%d names\n",
+ i);
+
+ ch_index++;
+ }
+
+ ipctl->gc.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)
@@ -928,9 +1282,11 @@ int s32_pinctrl_probe(struct platform_device *pdev,
#ifdef CONFIG_PM_SLEEP
struct s32_pinctrl_context *saved_context;
#endif
+ const struct s32_gpio_range *last_range;
struct pinctrl_desc *s32_pinctrl_desc;
struct s32_pinctrl_soc_info *info;
struct s32_pinctrl *ipctl;
+ struct gpio_chip *gc;
int ret;
if (!soc_data || !soc_data->pins || !soc_data->npins)
@@ -974,6 +1330,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)
@@ -997,5 +1358,43 @@ int s32_pinctrl_probe(struct platform_device *pdev,
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;
+
+ gc = &ipctl->gc;
+ gc->parent = &pdev->dev;
+ gc->label = dev_name(&pdev->dev);
+ gc->base = -1;
+ /*
+ * In some cases, there is a gap between the SIUL GPIOs.
+ *
+ * gpio_ranges[] is expected to be sorted by increasing gpio_base.
+ * ngpio is derived from the last range and must cover the highest
+ * GPIO offset, even when gaps exist in the numbering.
+ */
+ last_range = &soc_data->gpio_ranges[soc_data->num_gpio_ranges - 1];
+ gc->ngpio = last_range->gpio_base + last_range->gpio_num;
+ ret = s32_gpio_populate_names(&pdev->dev, ipctl);
+ if (ret)
+ return ret;
+
+ gc->set = s32_gpio_set;
+ gc->get = s32_gpio_get;
+ gc->set_config = gpiochip_generic_config;
+ gc->request = s32_gpio_request;
+ gc->free = s32_gpio_free;
+ gc->direction_output = s32_gpio_dir_out;
+ gc->direction_input = s32_gpio_dir_in;
+ gc->get_direction = s32_gpio_get_dir;
+ gc->init_valid_mask = s32_init_valid_mask;
+
+ ret = devm_gpiochip_add_data(&pdev->dev, gc, ipctl);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Unable to add gpiochip\n");
+
+ dev_info(&pdev->dev, "Initialized S32 GPIO functionality\n");
+
return 0;
}
diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c
index c49d28793b69..b1bf328371e2 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,36 @@ 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, 102),
+ S32_GPIO_RANGE(112, 79),
+};
+
+/* 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),
};
static const struct of_device_id s32_pinctrl_of_match[] = {
+ {
+ .compatible = "nxp,s32g2-siul2-pinctrl-gpio",
+ .data = &s32g_pinctrl_data,
+ },
{
.compatible = "nxp,s32g2-siul2-pinctrl",
- .data = &s32_pinctrl_data,
+ .data = &legacy_s32g_pinctrl_data,
},
{ /* sentinel */ }
};
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 7/7] arm64: dts: s32g: describe GPIO and EIRQ resources in SIUL2 pinctrl node
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
` (5 preceding siblings ...)
2026-05-04 12:41 ` [PATCH 6/7] pinctrl: s32cc: implement GPIO functionality Khristine Andreea Barbulescu
@ 2026-05-04 12:41 ` Khristine Andreea Barbulescu
2026-05-04 13:14 ` [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
7 siblings, 0 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 12:41 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
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.
Add the new compatible string for SIUL2 pinctrl nodes
that describe GPIO and EIRQ resources and keep the existing
compatible to maintain compatibility with legacy bindings.
Reflect these resources in the SIUL2 pinctrl node by adding:
- "nxp,s32g2-siul2-pinctrl-gpio" compatible
- 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 | 26 +++++++++++++++++++++---
arch/arm64/boot/dts/freescale/s32g3.dtsi | 26 +++++++++++++++++++++---
2 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/s32g2.dtsi b/arch/arm64/boot/dts/freescale/s32g2.dtsi
index 51d00dac12de..b3bef4ee559d 100644
--- a/arch/arm64/boot/dts/freescale/s32g2.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g2.dtsi
@@ -3,7 +3,7 @@
* NXP S32G2 SoC family
*
* Copyright (c) 2021 SUSE LLC
- * Copyright 2017-2021, 2024-2025 NXP
+ * Copyright 2017-2021, 2024-2026 NXP
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -123,7 +123,8 @@ rtc0: rtc@40060000 {
};
pinctrl: pinctrl@4009c240 {
- compatible = "nxp,s32g2-siul2-pinctrl";
+ compatible = "nxp,s32g2-siul2-pinctrl-gpio",
+ "nxp,s32g2-siul2-pinctrl";
/* MSCR0-MSCR101 registers on siul2_0 */
reg = <0x4009c240 0x198>,
/* MSCR112-MSCR122 registers on siul2_1 */
@@ -135,7 +136,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 102 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 e314f3c7d61d..3b38500d7d05 100644
--- a/arch/arm64/boot/dts/freescale/s32g3.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g3.dtsi
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
- * Copyright 2021-2025 NXP
+ * Copyright 2021-2026 NXP
*
* Authors: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
* Ciprian Costea <ciprianmarian.costea@nxp.com>
@@ -181,7 +181,8 @@ rtc0: rtc@40060000 {
};
pinctrl: pinctrl@4009c240 {
- compatible = "nxp,s32g2-siul2-pinctrl";
+ compatible = "nxp,s32g2-siul2-pinctrl-gpio",
+ "nxp,s32g2-siul2-pinctrl";
/* MSCR0-MSCR101 registers on siul2_0 */
reg = <0x4009c240 0x198>,
/* MSCR112-MSCR122 registers on siul2_1 */
@@ -193,7 +194,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 102 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 [flat|nested] 9+ messages in thread
* Re: [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
` (6 preceding siblings ...)
2026-05-04 12:41 ` [PATCH 7/7] arm64: dts: s32g: describe GPIO and EIRQ resources in SIUL2 pinctrl node Khristine Andreea Barbulescu
@ 2026-05-04 13:14 ` Khristine Andreea Barbulescu
7 siblings, 0 replies; 9+ messages in thread
From: Khristine Andreea Barbulescu @ 2026-05-04 13:14 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
On 5/4/2026 3:41 PM, Khristine Andreea Barbulescu wrote:
> This patch series adds support for basic GPIO
> operations(set, get, direction_output/input, set_config).
>
> 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.
>
> 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 (5):
> pinctrl: s32cc: use dev_err_probe() and improve error messages
> 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 | 107 ++-
> arch/arm64/boot/dts/freescale/s32g2.dtsi | 26 +-
> arch/arm64/boot/dts/freescale/s32g3.dtsi | 26 +-
> drivers/pinctrl/nxp/pinctrl-s32.h | 15 +-
> drivers/pinctrl/nxp/pinctrl-s32cc.c | 646 ++++++++++++++----
> drivers/pinctrl/nxp/pinctrl-s32g2.c | 25 +-
> 6 files changed, 707 insertions(+), 138 deletions(-)
>
Hello,
Please disregard the submission of this patch series.
I have resent it because this version did not
have the "v9" tag appended in the patch subjects.
Regards,
Khristine
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-05-04 13:14 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-04 12:41 [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 1/7] pinctrl: s32cc: use dev_err_probe() and improve error messages Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 2/7] pinctrl: s32cc: add/fix some comments Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 3/7] pinctrl: s32cc: remove inline specifiers Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 4/7] pinctrl: s32cc: change to "devm_pinctrl_register_and_init" Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 5/7] dt-bindings: pinctrl: s32g2-siul2: describe GPIO and EIRQ resources Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 6/7] pinctrl: s32cc: implement GPIO functionality Khristine Andreea Barbulescu
2026-05-04 12:41 ` [PATCH 7/7] arm64: dts: s32g: describe GPIO and EIRQ resources in SIUL2 pinctrl node Khristine Andreea Barbulescu
2026-05-04 13:14 ` [PATCH 0/7] gpio: siul2-s32g2: add initial GPIO driver Khristine Andreea Barbulescu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox