* [PATCH v2 1/9] pinctrl: pinconf-generic: Add property "skew-delay-direction"
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 2/9] dt-bindings: pincfg-node: " Antonio Borneo
` (7 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
Add the property "skew-delay-direction" to the generic parameters
used for parsing DT files. This allows to specify the direction
(either input, output or both) on which the existing property
"skew-delay" applies.
For backward compatibility, set default to 0, equivalent to "both
input and output directions".
This enables drivers that use the generic pin configuration to get
the value passed through this new property.
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
drivers/pinctrl/pinconf-generic.c | 2 ++
include/linux/pinctrl/pinconf-generic.h | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index d67838afb0857..d2713fce0ab0f 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -54,6 +54,7 @@ static const struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_SLEEP_HARDWARE_STATE, "sleep hardware state", NULL, false),
PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL, true),
PCONFDUMP(PIN_CONFIG_SKEW_DELAY, "skew delay", NULL, true),
+ PCONFDUMP(PIN_CONFIG_SKEW_DELAY_DIRECTION, "skew delay direction", NULL, true),
};
static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev,
@@ -190,6 +191,7 @@ static const struct pinconf_generic_params dt_params[] = {
{ "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 },
{ "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
{ "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 },
+ { "skew-delay-direction", PIN_CONFIG_SKEW_DELAY_DIRECTION, 0 },
};
/**
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
index 1bcf071b860eb..7e49d4e60b9fb 100644
--- a/include/linux/pinctrl/pinconf-generic.h
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -108,6 +108,11 @@ struct pinctrl_map;
* or latch delay (on outputs) this parameter (in a custom format)
* specifies the clock skew or latch delay. It typically controls how
* many double inverters are put in front of the line.
+ * @PIN_CONFIG_SKEW_DELAY_DIRECTION: this will configure the direction of the
+ * skew rate or latch delay. If not present or it's 0, latch delay (on
+ * outputs) and/or skew rate (on inputs) is applied. If it's 1, then only
+ * latch delay on outputs is applied. If it's 2, then only skew rate on
+ * inputs is applied.
* @PIN_CONFIG_SLEEP_HARDWARE_STATE: indicate this is sleep related state.
* @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to
* this parameter (on a custom format) tells the driver which alternative
@@ -143,6 +148,7 @@ enum pin_config_param {
PIN_CONFIG_PERSIST_STATE,
PIN_CONFIG_POWER_SOURCE,
PIN_CONFIG_SKEW_DELAY,
+ PIN_CONFIG_SKEW_DELAY_DIRECTION,
PIN_CONFIG_SLEEP_HARDWARE_STATE,
PIN_CONFIG_SLEW_RATE,
PIN_CONFIG_END = 0x7F,
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v2 2/9] dt-bindings: pincfg-node: Add property "skew-delay-direction"
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 1/9] pinctrl: pinconf-generic: Add property "skew-delay-direction" Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
2025-09-10 2:08 ` Rob Herring (Arm)
2025-09-30 12:23 ` Linus Walleij
2025-09-05 13:55 ` [PATCH v2 3/9] pinctrl: stm32: Rework stm32_pconf_parse_conf() Antonio Borneo
` (6 subsequent siblings)
8 siblings, 2 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
Add the property "skew-delay-direction" to specify on which pin's
direction (either input, output or both) the value of the generic
property 'skew-delay' applies.
For backward compatibility, 'skew-delay' applies on both input and
output directions when the new property is not present or has
value '0'.
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
.../devicetree/bindings/pinctrl/pincfg-node.yaml | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml b/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
index cbfcf215e571d..dd3b8cb817ff7 100644
--- a/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
@@ -151,6 +151,17 @@ properties:
this affects the expected clock skew on input pins
and the delay before latching a value to an output
pin. Typically indicates how many double-inverters are
- used to delay the signal.
+ used to delay the signal. The delay is assumed as present
+ on both input and output directions of the pins, unless
+ otherwise specified by the property "skew-delay-direction"
+
+ skew-delay-direction:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2]
+ default: 0
+ description: |
+ 0: skew-delay applies to both input and output directions
+ 1: skew-delay applies only to the output direction
+ 2: skew-delay applies only to the input direction
additionalProperties: true
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v2 2/9] dt-bindings: pincfg-node: Add property "skew-delay-direction"
2025-09-05 13:55 ` [PATCH v2 2/9] dt-bindings: pincfg-node: " Antonio Borneo
@ 2025-09-10 2:08 ` Rob Herring (Arm)
2025-09-30 12:23 ` Linus Walleij
1 sibling, 0 replies; 14+ messages in thread
From: Rob Herring (Arm) @ 2025-09-10 2:08 UTC (permalink / raw)
To: Antonio Borneo
Cc: linux-kernel, linux-gpio, Christophe Roullier, Maxime Coquelin,
Alexandre Torgue, Fabien Dessenne, linux-stm32, Conor Dooley,
Linus Walleij, Bartosz Golaszewski, linux-arm-kernel,
Valentin Caron, Krzysztof Kozlowski, devicetree
On Fri, 05 Sep 2025 15:55:40 +0200, Antonio Borneo wrote:
> Add the property "skew-delay-direction" to specify on which pin's
> direction (either input, output or both) the value of the generic
> property 'skew-delay' applies.
> For backward compatibility, 'skew-delay' applies on both input and
> output directions when the new property is not present or has
> value '0'.
>
> Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
> ---
> .../devicetree/bindings/pinctrl/pincfg-node.yaml | 13 ++++++++++++-
> 1 file changed, 12 insertions(+), 1 deletion(-)
>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/9] dt-bindings: pincfg-node: Add property "skew-delay-direction"
2025-09-05 13:55 ` [PATCH v2 2/9] dt-bindings: pincfg-node: " Antonio Borneo
2025-09-10 2:08 ` Rob Herring (Arm)
@ 2025-09-30 12:23 ` Linus Walleij
2025-10-01 14:36 ` Antonio Borneo
1 sibling, 1 reply; 14+ messages in thread
From: Linus Walleij @ 2025-09-30 12:23 UTC (permalink / raw)
To: Antonio Borneo
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Bartosz Golaszewski, linux-gpio, devicetree,
linux-kernel, linux-stm32, linux-arm-kernel, Christophe Roullier,
Fabien Dessenne, Valentin Caron
Hi Antonio,
thanks for your patch!
And sorry that it takes so long for me to review it! :(
On Fri, Sep 5, 2025 at 3:56 PM Antonio Borneo
<antonio.borneo@foss.st.com> wrote:
> Add the property "skew-delay-direction" to specify on which pin's
> direction (either input, output or both) the value of the generic
> property 'skew-delay' applies.
> For backward compatibility, 'skew-delay' applies on both input and
> output directions when the new property is not present or has
> value '0'.
>
> Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
(...)
> + skew-delay-direction:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + enum: [0, 1, 2]
> + default: 0
> + description: |
> + 0: skew-delay applies to both input and output directions
> + 1: skew-delay applies only to the output direction
> + 2: skew-delay applies only to the input direction
Unfortunately I don't think this will work, because skew-delay
has a value, and with this scheme we can only specify that we
want this value to affect both in/out, only in or only out.
What happens when someone want to configure different
skew delay for input and output?
I think it is better to add:
skew-delay-input = <u32>;
skew-delay-output = <u32>;
So the drivers that need this explicitly specified will need
to just define one of these instead.
If you want to be very determined, make the schema
not accept skew-delay if either skew-delay-input
or skew-delay-output is specified.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/9] dt-bindings: pincfg-node: Add property "skew-delay-direction"
2025-09-30 12:23 ` Linus Walleij
@ 2025-10-01 14:36 ` Antonio Borneo
0 siblings, 0 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-10-01 14:36 UTC (permalink / raw)
To: Linus Walleij
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Bartosz Golaszewski, linux-gpio, devicetree,
linux-kernel, linux-stm32, linux-arm-kernel, Christophe Roullier,
Fabien Dessenne, Valentin Caron
On Tue, 2025-09-30 at 14:23 +0200, Linus Walleij wrote:
> Hi Antonio,
>
> thanks for your patch!
>
> And sorry that it takes so long for me to review it! :(
Hi Linus,
no problem, thanks for your review!
>
> On Fri, Sep 5, 2025 at 3:56 PM Antonio Borneo
> <antonio.borneo@foss.st.com> wrote:
>
> > Add the property "skew-delay-direction" to specify on which pin's
> > direction (either input, output or both) the value of the generic
> > property 'skew-delay' applies.
> > For backward compatibility, 'skew-delay' applies on both input and
> > output directions when the new property is not present or has
> > value '0'.
> >
> > Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
> (...)
> > + skew-delay-direction:
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + enum: [0, 1, 2]
> > + default: 0
> > + description: |
> > + 0: skew-delay applies to both input and output directions
> > + 1: skew-delay applies only to the output direction
> > + 2: skew-delay applies only to the input direction
>
> Unfortunately I don't think this will work, because skew-delay
> has a value, and with this scheme we can only specify that we
> want this value to affect both in/out, only in or only out.
>
> What happens when someone want to configure different
> skew delay for input and output?
It makes sense!
I will address it in V3.
> I think it is better to add:
>
> skew-delay-input = <u32>;
> skew-delay-output = <u32>;
>
> So the drivers that need this explicitly specified will need
> to just define one of these instead.
>
> If you want to be very determined, make the schema
> not accept skew-delay if either skew-delay-input
> or skew-delay-output is specified.
Sure, I will add the proper test.
Regards,
Antonio
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 3/9] pinctrl: stm32: Rework stm32_pconf_parse_conf()
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 1/9] pinctrl: pinconf-generic: Add property "skew-delay-direction" Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 2/9] dt-bindings: pincfg-node: " Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 4/9] pinctrl: stm32: Simplify handling of backup pin status Antonio Borneo
` (5 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
Reduce the number of parameters of the function by moving inside
the decoding of the field 'config'.
While there:
- change the type of 'param' to 'unsigned int' to handle the extra
values not in 'enum pin_config_param';
- change the type of 'arg' to 'u32' to avoid additional conversions
and align to 'u32' the corresponding param of __stm32_gpio_set().
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
drivers/pinctrl/stm32/pinctrl-stm32.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 823c8fe758e2c..baf160a71c11c 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -287,7 +287,7 @@ static void stm32_gpio_rif_release_semaphore(struct stm32_gpio_bank *bank, unsig
/* GPIO functions */
static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank,
- unsigned offset, int value)
+ unsigned int offset, u32 value)
{
stm32_gpio_backup_value(bank, offset, value);
@@ -1195,10 +1195,11 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
}
static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
- unsigned int pin, enum pin_config_param param,
- enum pin_config_param arg)
+ unsigned int pin, unsigned long config)
{
struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int param = pinconf_to_config_param(config);
+ u32 arg = pinconf_to_config_argument(config);
struct pinctrl_gpio_range *range;
struct stm32_gpio_bank *bank;
int offset, ret = 0;
@@ -1267,9 +1268,7 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
for (i = 0; i < num_configs; i++) {
mutex_lock(&pctldev->mutex);
- ret = stm32_pconf_parse_conf(pctldev, g->pin,
- pinconf_to_config_param(configs[i]),
- pinconf_to_config_argument(configs[i]));
+ ret = stm32_pconf_parse_conf(pctldev, g->pin, configs[i]);
mutex_unlock(&pctldev->mutex);
if (ret < 0)
return ret;
@@ -1286,9 +1285,7 @@ static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
int i, ret;
for (i = 0; i < num_configs; i++) {
- ret = stm32_pconf_parse_conf(pctldev, pin,
- pinconf_to_config_param(configs[i]),
- pinconf_to_config_argument(configs[i]));
+ ret = stm32_pconf_parse_conf(pctldev, pin, configs[i]);
if (ret < 0)
return ret;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v2 4/9] pinctrl: stm32: Simplify handling of backup pin status
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
` (2 preceding siblings ...)
2025-09-05 13:55 ` [PATCH v2 3/9] pinctrl: stm32: Rework stm32_pconf_parse_conf() Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 5/9] pinctrl: stm32: Drop useless spinlock save and restore Antonio Borneo
` (4 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
Use C bit-field to keep the backup of the pin status, instead of
explicitly handling the bit-field through shift and mask of a u32
container.
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
drivers/pinctrl/stm32/pinctrl-stm32.c | 70 +++++++++------------------
1 file changed, 24 insertions(+), 46 deletions(-)
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index baf160a71c11c..741f503b6c44c 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -54,18 +54,6 @@
#define STM32_GPIO_CIDCFGR(x) (0x50 + (0x8 * (x)))
#define STM32_GPIO_SEMCR(x) (0x54 + (0x8 * (x)))
-/* custom bitfield to backup pin status */
-#define STM32_GPIO_BKP_MODE_SHIFT 0
-#define STM32_GPIO_BKP_MODE_MASK GENMASK(1, 0)
-#define STM32_GPIO_BKP_ALT_SHIFT 2
-#define STM32_GPIO_BKP_ALT_MASK GENMASK(5, 2)
-#define STM32_GPIO_BKP_SPEED_SHIFT 6
-#define STM32_GPIO_BKP_SPEED_MASK GENMASK(7, 6)
-#define STM32_GPIO_BKP_PUPD_SHIFT 8
-#define STM32_GPIO_BKP_PUPD_MASK GENMASK(9, 8)
-#define STM32_GPIO_BKP_TYPE 10
-#define STM32_GPIO_BKP_VAL 11
-
#define STM32_GPIO_CIDCFGR_CFEN BIT(0)
#define STM32_GPIO_CIDCFGR_SEMEN BIT(1)
#define STM32_GPIO_CIDCFGR_SCID_MASK GENMASK(5, 4)
@@ -100,6 +88,15 @@ struct stm32_pinctrl_group {
unsigned pin;
};
+struct stm32_pin_backup {
+ unsigned int alt:4;
+ unsigned int mode:2;
+ unsigned int bias:2;
+ unsigned int speed:2;
+ unsigned int drive:1;
+ unsigned int value:1;
+};
+
struct stm32_gpio_bank {
void __iomem *base;
struct reset_control *rstc;
@@ -110,7 +107,7 @@ struct stm32_gpio_bank {
struct irq_domain *domain;
u32 bank_nr;
u32 bank_ioport_nr;
- u32 pin_backup[STM32_GPIO_PINS_PER_BANK];
+ struct stm32_pin_backup pin_backup[STM32_GPIO_PINS_PER_BANK];
u8 irq_type[STM32_GPIO_PINS_PER_BANK];
bool secure_control;
bool rif_control;
@@ -176,38 +173,32 @@ static inline u32 stm32_gpio_get_alt(u32 function)
static void stm32_gpio_backup_value(struct stm32_gpio_bank *bank,
u32 offset, u32 value)
{
- bank->pin_backup[offset] &= ~BIT(STM32_GPIO_BKP_VAL);
- bank->pin_backup[offset] |= value << STM32_GPIO_BKP_VAL;
+ bank->pin_backup[offset].value = value;
}
static void stm32_gpio_backup_mode(struct stm32_gpio_bank *bank, u32 offset,
u32 mode, u32 alt)
{
- bank->pin_backup[offset] &= ~(STM32_GPIO_BKP_MODE_MASK |
- STM32_GPIO_BKP_ALT_MASK);
- bank->pin_backup[offset] |= mode << STM32_GPIO_BKP_MODE_SHIFT;
- bank->pin_backup[offset] |= alt << STM32_GPIO_BKP_ALT_SHIFT;
+ bank->pin_backup[offset].mode = mode;
+ bank->pin_backup[offset].alt = alt;
}
static void stm32_gpio_backup_driving(struct stm32_gpio_bank *bank, u32 offset,
u32 drive)
{
- bank->pin_backup[offset] &= ~BIT(STM32_GPIO_BKP_TYPE);
- bank->pin_backup[offset] |= drive << STM32_GPIO_BKP_TYPE;
+ bank->pin_backup[offset].drive = drive;
}
static void stm32_gpio_backup_speed(struct stm32_gpio_bank *bank, u32 offset,
u32 speed)
{
- bank->pin_backup[offset] &= ~STM32_GPIO_BKP_SPEED_MASK;
- bank->pin_backup[offset] |= speed << STM32_GPIO_BKP_SPEED_SHIFT;
+ bank->pin_backup[offset].speed = speed;
}
static void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank, u32 offset,
u32 bias)
{
- bank->pin_backup[offset] &= ~STM32_GPIO_BKP_PUPD_MASK;
- bank->pin_backup[offset] |= bias << STM32_GPIO_BKP_PUPD_SHIFT;
+ bank->pin_backup[offset].bias = bias;
}
/* RIF functions */
@@ -1798,7 +1789,7 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs(
struct stm32_pinctrl *pctl, u32 pin)
{
const struct pin_desc *desc = pin_desc_get(pctl->pctl_dev, pin);
- u32 val, alt, mode, offset = stm32_gpio_pin(pin);
+ u32 mode, offset = stm32_gpio_pin(pin);
struct pinctrl_gpio_range *range;
struct stm32_gpio_bank *bank;
bool pin_is_irq;
@@ -1818,36 +1809,23 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs(
bank = gpiochip_get_data(range->gc);
- alt = bank->pin_backup[offset] & STM32_GPIO_BKP_ALT_MASK;
- alt >>= STM32_GPIO_BKP_ALT_SHIFT;
- mode = bank->pin_backup[offset] & STM32_GPIO_BKP_MODE_MASK;
- mode >>= STM32_GPIO_BKP_MODE_SHIFT;
-
- ret = stm32_pmx_set_mode(bank, offset, mode, alt);
+ mode = bank->pin_backup[offset].mode;
+ ret = stm32_pmx_set_mode(bank, offset, mode, bank->pin_backup[offset].alt);
if (ret)
return ret;
- if (mode == 1) {
- val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_VAL);
- val = val >> STM32_GPIO_BKP_VAL;
- __stm32_gpio_set(bank, offset, val);
- }
+ if (mode == 1)
+ __stm32_gpio_set(bank, offset, bank->pin_backup[offset].value);
- val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_TYPE);
- val >>= STM32_GPIO_BKP_TYPE;
- ret = stm32_pconf_set_driving(bank, offset, val);
+ ret = stm32_pconf_set_driving(bank, offset, bank->pin_backup[offset].drive);
if (ret)
return ret;
- val = bank->pin_backup[offset] & STM32_GPIO_BKP_SPEED_MASK;
- val >>= STM32_GPIO_BKP_SPEED_SHIFT;
- ret = stm32_pconf_set_speed(bank, offset, val);
+ ret = stm32_pconf_set_speed(bank, offset, bank->pin_backup[offset].speed);
if (ret)
return ret;
- val = bank->pin_backup[offset] & STM32_GPIO_BKP_PUPD_MASK;
- val >>= STM32_GPIO_BKP_PUPD_SHIFT;
- ret = stm32_pconf_set_bias(bank, offset, val);
+ ret = stm32_pconf_set_bias(bank, offset, bank->pin_backup[offset].bias);
if (ret)
return ret;
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v2 5/9] pinctrl: stm32: Drop useless spinlock save and restore
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
` (3 preceding siblings ...)
2025-09-05 13:55 ` [PATCH v2 4/9] pinctrl: stm32: Simplify handling of backup pin status Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 6/9] pinctrl: stm32: Avoid keeping a bool value in a u32 variable Antonio Borneo
` (3 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
There is no need to acquire a spinlock to only read a register for
debugfs reporting.
Drop such useless spinlock save and restore.
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
drivers/pinctrl/stm32/pinctrl-stm32.c | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 741f503b6c44c..76555d18720f6 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -920,9 +920,6 @@ static void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode,
u32 val;
int alt_shift = (pin % 8) * 4;
int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4;
- unsigned long flags;
-
- spin_lock_irqsave(&bank->lock, flags);
val = readl_relaxed(bank->base + alt_offset);
val &= GENMASK(alt_shift + 3, alt_shift);
@@ -931,8 +928,6 @@ static void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode,
val = readl_relaxed(bank->base + STM32_GPIO_MODER);
val &= GENMASK(pin * 2 + 1, pin * 2);
*mode = val >> (pin * 2);
-
- spin_unlock_irqrestore(&bank->lock, flags);
}
static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev,
@@ -1050,16 +1045,11 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
unsigned int offset)
{
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&bank->lock, flags);
-
val = readl_relaxed(bank->base + STM32_GPIO_TYPER);
val &= BIT(offset);
- spin_unlock_irqrestore(&bank->lock, flags);
-
return (val >> offset);
}
@@ -1101,16 +1091,11 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
unsigned int offset)
{
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&bank->lock, flags);
-
val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR);
val &= GENMASK(offset * 2 + 1, offset * 2);
- spin_unlock_irqrestore(&bank->lock, flags);
-
return (val >> (offset * 2));
}
@@ -1152,27 +1137,19 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
unsigned int offset)
{
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&bank->lock, flags);
-
val = readl_relaxed(bank->base + STM32_GPIO_PUPDR);
val &= GENMASK(offset * 2 + 1, offset * 2);
- spin_unlock_irqrestore(&bank->lock, flags);
-
return (val >> (offset * 2));
}
static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
unsigned int offset, bool dir)
{
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&bank->lock, flags);
-
if (dir)
val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) &
BIT(offset));
@@ -1180,8 +1157,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) &
BIT(offset));
- spin_unlock_irqrestore(&bank->lock, flags);
-
return val;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v2 6/9] pinctrl: stm32: Avoid keeping a bool value in a u32 variable
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
` (4 preceding siblings ...)
2025-09-05 13:55 ` [PATCH v2 5/9] pinctrl: stm32: Drop useless spinlock save and restore Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 7/9] pinctrl: stm32: Support I/O synchronization parameters Antonio Borneo
` (2 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
Change type of variable to avoid keeping the bool return value in
a variable of u32 type.
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 76555d18720f6..8d2f409342313 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -1148,7 +1148,7 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
unsigned int offset, bool dir)
{
- u32 val;
+ bool val;
if (dir)
val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) &
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v2 7/9] pinctrl: stm32: Support I/O synchronization parameters
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
` (5 preceding siblings ...)
2025-09-05 13:55 ` [PATCH v2 6/9] pinctrl: stm32: Avoid keeping a bool value in a u32 variable Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 8/9] dt-bindings: " Antonio Borneo
2025-09-05 13:55 ` [PATCH v2 9/9] arm64: dts: st: Add I/O sync to eth2 pinctrl in stm32mp25-pinctrl.dtsi Antonio Borneo
8 siblings, 0 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
Devices in the stm32mp2xx family include an I/O synchronization
block on each pin that is used to fine tune and improve the I/O
timing margins of high speed synchronous interfaces.
It can be configured to provide independently for each pin:
- skew rate on input direction or latch delay on output direction;
- inversion of clock signals or re-sampling of data signals.
Add support for the generic properties:
- skew-delay;
- skew-delay-direction.
Add support for the property 'st,io-sync' to configure clock
inversion or data re-sampling mode.
Show the new parameters on debugfs pinconf-pins.
Enable it for the stm32mp257 pinctrl driver.
Co-developed-by: Valentin Caron <valentin.caron@foss.st.com>
Signed-off-by: Valentin Caron <valentin.caron@foss.st.com>
Co-developed-by: Fabien Dessenne <fabien.dessenne@foss.st.com>
Signed-off-by: Fabien Dessenne <fabien.dessenne@foss.st.com>
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
drivers/pinctrl/stm32/pinctrl-stm32.c | 235 +++++++++++++++++++++
drivers/pinctrl/stm32/pinctrl-stm32.h | 1 +
drivers/pinctrl/stm32/pinctrl-stm32mp257.c | 2 +
3 files changed, 238 insertions(+)
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 8d2f409342313..f5026e34f97f4 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -51,9 +51,21 @@
#define STM32_GPIO_AFRL 0x20
#define STM32_GPIO_AFRH 0x24
#define STM32_GPIO_SECCFGR 0x30
+#define STM32_GPIO_DELAYRL 0x40
+#define STM32_GPIO_ADVCFGRL 0x48
#define STM32_GPIO_CIDCFGR(x) (0x50 + (0x8 * (x)))
#define STM32_GPIO_SEMCR(x) (0x54 + (0x8 * (x)))
+#define STM32_GPIO_ADVCFGR_DLYPATH_MASK BIT(0)
+#define STM32_GPIO_ADVCFGR_DE_MASK BIT(1)
+#define STM32_GPIO_ADVCFGR_INVCLK_MASK BIT(2)
+#define STM32_GPIO_ADVCFGR_RET_MASK BIT(3)
+#define STM32_GPIO_ADVCFGR_IO_SYNC_MASK \
+ (STM32_GPIO_ADVCFGR_DE_MASK \
+ | STM32_GPIO_ADVCFGR_INVCLK_MASK \
+ | STM32_GPIO_ADVCFGR_RET_MASK)
+#define STM32_GPIO_ADVCFGR_MASK (STM32_GPIO_ADVCFGR_DLYPATH_MASK | STM32_GPIO_ADVCFGR_IO_SYNC_MASK)
+
#define STM32_GPIO_CIDCFGR_CFEN BIT(0)
#define STM32_GPIO_CIDCFGR_SEMEN BIT(1)
#define STM32_GPIO_CIDCFGR_SCID_MASK GENMASK(5, 4)
@@ -67,6 +79,9 @@
#define SYSCFG_IRQMUX_MASK GENMASK(3, 0)
+/* Vendor specific pin configurations */
+#define STM32_GPIO_PIN_CONFIG_IO_SYNC (PIN_CONFIG_END + 1)
+
#define gpio_range_to_bank(chip) \
container_of(chip, struct stm32_gpio_bank, range)
@@ -82,6 +97,23 @@ static const char * const stm32_gpio_functions[] = {
"reserved",
};
+static const struct pinconf_generic_params stm32_gpio_bindings[] = {
+ {"st,io-sync", STM32_GPIO_PIN_CONFIG_IO_SYNC, 0},
+};
+
+static u8 io_sync_2_advcfgr[] = {
+ /* data or clock GPIO pass-through */
+ [0] = 0,
+ /* clock GPIO inverted */
+ [1] = STM32_GPIO_ADVCFGR_INVCLK_MASK,
+ /* data GPIO re-sampled on clock rising edge */
+ [2] = STM32_GPIO_ADVCFGR_RET_MASK,
+ /* data GPIO re-sampled on clock falling edge */
+ [3] = STM32_GPIO_ADVCFGR_RET_MASK | STM32_GPIO_ADVCFGR_INVCLK_MASK,
+ /* data GPIO re-sampled on both clock edges */
+ [4] = STM32_GPIO_ADVCFGR_RET_MASK | STM32_GPIO_ADVCFGR_DE_MASK,
+};
+
struct stm32_pinctrl_group {
const char *name;
unsigned long config;
@@ -95,6 +127,8 @@ struct stm32_pin_backup {
unsigned int speed:2;
unsigned int drive:1;
unsigned int value:1;
+ unsigned int advcfg:4;
+ unsigned int skew_delay:4;
};
struct stm32_gpio_bank {
@@ -110,6 +144,7 @@ struct stm32_gpio_bank {
struct stm32_pin_backup pin_backup[STM32_GPIO_PINS_PER_BANK];
u8 irq_type[STM32_GPIO_PINS_PER_BANK];
bool secure_control;
+ bool io_sync_control;
bool rif_control;
};
@@ -201,6 +236,21 @@ static void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank, u32 offset,
bank->pin_backup[offset].bias = bias;
}
+static void stm32_gpio_backup_advcfg(struct stm32_gpio_bank *bank, u32 offset, u32 mask, u32 value)
+{
+ u32 val;
+
+ val = bank->pin_backup[offset].advcfg;
+ val &= ~mask;
+ val |= value & mask;
+ bank->pin_backup[offset].advcfg = val;
+}
+
+static void stm32_gpio_backup_skew_delay(struct stm32_gpio_bank *bank, u32 offset, u32 delay)
+{
+ bank->pin_backup[offset].skew_delay = delay;
+}
+
/* RIF functions */
static bool stm32_gpio_rif_valid(struct stm32_gpio_bank *bank, unsigned int gpio_nr)
@@ -1145,6 +1195,150 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
return (val >> (offset * 2));
}
+static int stm32_pconf_set_advcfgr(struct stm32_gpio_bank *bank, int offset, u32 mask, u32 value)
+{
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
+ int advcfgr_offset = STM32_GPIO_ADVCFGRL + (offset / 8) * 4;
+ int advcfgr_shift = (offset % 8) * 4;
+ unsigned long flags;
+ int err = 0;
+ u32 val;
+
+ if (!bank->io_sync_control)
+ return -ENOTSUPP;
+
+ spin_lock_irqsave(&bank->lock, flags);
+
+ if (pctl->hwlock) {
+ err = hwspin_lock_timeout_in_atomic(pctl->hwlock, HWSPNLCK_TIMEOUT);
+ if (err) {
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
+ goto unlock;
+ }
+ }
+
+ val = readl_relaxed(bank->base + advcfgr_offset);
+ val &= ~(mask << advcfgr_shift);
+ val |= (value & mask) << advcfgr_shift;
+ writel_relaxed(val, bank->base + advcfgr_offset);
+
+ if (pctl->hwlock)
+ hwspin_unlock_in_atomic(pctl->hwlock);
+
+ stm32_gpio_backup_advcfg(bank, offset, mask, value);
+
+unlock:
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ return err;
+}
+
+static u32 stm32_pconf_get_advcfgr(struct stm32_gpio_bank *bank, int offset, u32 mask)
+{
+ int advcfgr_offset = STM32_GPIO_ADVCFGRL + (offset / 8) * 4;
+ int advcfgr_shift = (offset % 8) * 4;
+ u32 val;
+
+ if (!bank->io_sync_control)
+ return 0;
+
+ val = readl_relaxed(bank->base + advcfgr_offset);
+ val >>= advcfgr_shift;
+
+ return val & mask;
+}
+
+static int stm32_pconf_set_skew_dir(struct stm32_gpio_bank *bank, int offset, u32 dir)
+{
+ return stm32_pconf_set_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_DLYPATH_MASK,
+ (dir == 2) ? STM32_GPIO_ADVCFGR_DLYPATH_MASK : 0);
+}
+
+static const char *stm32_pconf_get_skew_dir_str(struct stm32_gpio_bank *bank, int offset)
+{
+ return stm32_pconf_get_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_DLYPATH_MASK) ?
+ "input" : "output";
+}
+
+static int stm32_pconf_set_io_sync(struct stm32_gpio_bank *bank, int offset, u32 io_sync)
+{
+ if (io_sync >= ARRAY_SIZE(io_sync_2_advcfgr))
+ return -EINVAL;
+
+ return stm32_pconf_set_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_IO_SYNC_MASK,
+ io_sync_2_advcfgr[io_sync]);
+}
+
+static const char *stm32_pconf_get_io_sync_str(struct stm32_gpio_bank *bank, int offset)
+{
+ u32 io_sync = stm32_pconf_get_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_IO_SYNC_MASK);
+
+ if (io_sync & STM32_GPIO_ADVCFGR_RET_MASK) {
+ if (io_sync & STM32_GPIO_ADVCFGR_DE_MASK)
+ return "data GPIO re-sampled on both clock edges";
+
+ if (io_sync & STM32_GPIO_ADVCFGR_INVCLK_MASK)
+ return "data GPIO re-sampled on clock falling edge";
+
+ return "data GPIO re-sampled on clock rising edge";
+ }
+
+ if (io_sync & STM32_GPIO_ADVCFGR_INVCLK_MASK)
+ return "clock GPIO inverted";
+
+ return NULL;
+}
+
+static int stm32_pconf_set_skew_delay(struct stm32_gpio_bank *bank, int offset, u32 delay)
+{
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
+ int delay_offset = STM32_GPIO_DELAYRL + (offset / 8) * 4;
+ int delay_shift = (offset % 8) * 4;
+ unsigned long flags;
+ int err = 0;
+ u32 val;
+
+ if (!bank->io_sync_control)
+ return -ENOTSUPP;
+
+ spin_lock_irqsave(&bank->lock, flags);
+
+ if (pctl->hwlock) {
+ err = hwspin_lock_timeout_in_atomic(pctl->hwlock, HWSPNLCK_TIMEOUT);
+ if (err) {
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
+ goto unlock;
+ }
+ }
+
+ val = readl_relaxed(bank->base + delay_offset);
+ val &= ~GENMASK(delay_shift + 3, delay_shift);
+ val |= (delay << delay_shift);
+ writel_relaxed(val, bank->base + delay_offset);
+
+ if (pctl->hwlock)
+ hwspin_unlock_in_atomic(pctl->hwlock);
+
+ stm32_gpio_backup_skew_delay(bank, offset, delay);
+
+unlock:
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ return err;
+}
+
+static u32 stm32_pconf_get_skew_delay(struct stm32_gpio_bank *bank, int offset)
+{
+ int delay_offset = STM32_GPIO_DELAYRL + (offset / 8) * 4;
+ int delay_shift = (offset % 8) * 4;
+ u32 val;
+
+ val = readl_relaxed(bank->base + delay_offset);
+ val &= GENMASK(delay_shift + 3, delay_shift);
+
+ return val >> delay_shift;
+}
+
static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
unsigned int offset, bool dir)
{
@@ -1207,6 +1401,15 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
__stm32_gpio_set(bank, offset, arg);
ret = stm32_pmx_gpio_set_direction(pctldev, range, pin, false);
break;
+ case PIN_CONFIG_SKEW_DELAY:
+ ret = stm32_pconf_set_skew_delay(bank, offset, arg);
+ break;
+ case PIN_CONFIG_SKEW_DELAY_DIRECTION:
+ ret = stm32_pconf_set_skew_dir(bank, offset, arg);
+ break;
+ case STM32_GPIO_PIN_CONFIG_IO_SYNC:
+ ret = stm32_pconf_set_io_sync(bank, offset, arg);
+ break;
default:
ret = -ENOTSUPP;
}
@@ -1349,6 +1552,22 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
case 3:
break;
}
+
+ if (bank->io_sync_control) {
+ const char *io_sync_str, *skew_dir_str;
+ u32 skew_delay;
+
+ io_sync_str = stm32_pconf_get_io_sync_str(bank, offset);
+ skew_dir_str = stm32_pconf_get_skew_dir_str(bank, offset);
+ skew_delay = stm32_pconf_get_skew_delay(bank, offset);
+
+ if (io_sync_str)
+ seq_printf(s, " - IO-sync: %s", io_sync_str);
+
+ if (skew_delay)
+ seq_printf(s, " - Skew-delay: %u (%u ps) %s", skew_delay, skew_delay * 250,
+ skew_dir_str);
+ }
}
static const struct pinconf_ops stm32_pconf_ops = {
@@ -1441,6 +1660,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode
bank->bank_nr = bank_nr;
bank->bank_ioport_nr = bank_ioport_nr;
bank->secure_control = pctl->match_data->secure_control;
+ bank->io_sync_control = pctl->match_data->io_sync_control;
bank->rif_control = pctl->match_data->rif_control;
spin_lock_init(&bank->lock);
@@ -1683,6 +1903,8 @@ int stm32_pctl_probe(struct platform_device *pdev)
pctl->pctl_desc.confops = &stm32_pconf_ops;
pctl->pctl_desc.pctlops = &stm32_pctrl_ops;
pctl->pctl_desc.pmxops = &stm32_pmx_ops;
+ pctl->pctl_desc.num_custom_params = ARRAY_SIZE(stm32_gpio_bindings);
+ pctl->pctl_desc.custom_params = stm32_gpio_bindings;
pctl->dev = &pdev->dev;
pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc,
@@ -1804,6 +2026,19 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs(
if (ret)
return ret;
+ if (bank->io_sync_control) {
+ ret = stm32_pconf_set_skew_delay(bank, offset,
+ bank->pin_backup[offset].skew_delay);
+ if (ret)
+ return ret;
+
+ /* restore io_sync and skew_dir */
+ ret = stm32_pconf_set_advcfgr(bank, offset, STM32_GPIO_ADVCFGR_MASK,
+ bank->pin_backup[offset].advcfg);
+ if (ret)
+ return ret;
+ }
+
if (pin_is_irq)
regmap_field_write(pctl->irqmux[offset], bank->bank_ioport_nr);
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h
index b98a4141bf2c0..d17cbdbba4482 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.h
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.h
@@ -64,6 +64,7 @@ struct stm32_pinctrl_match_data {
const struct stm32_desc_pin *pins;
const unsigned int npins;
bool secure_control;
+ bool io_sync_control;
bool rif_control;
};
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp257.c b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c
index d226de524bfc1..6709bddd97186 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32mp257.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c
@@ -2543,6 +2543,7 @@ static const struct stm32_desc_pin stm32mp257_z_pins[] = {
static struct stm32_pinctrl_match_data stm32mp257_match_data = {
.pins = stm32mp257_pins,
.npins = ARRAY_SIZE(stm32mp257_pins),
+ .io_sync_control = true,
.secure_control = true,
.rif_control = true,
};
@@ -2550,6 +2551,7 @@ static struct stm32_pinctrl_match_data stm32mp257_match_data = {
static struct stm32_pinctrl_match_data stm32mp257_z_match_data = {
.pins = stm32mp257_z_pins,
.npins = ARRAY_SIZE(stm32mp257_z_pins),
+ .io_sync_control = true,
.secure_control = true,
.rif_control = true,
};
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v2 8/9] dt-bindings: pinctrl: stm32: Support I/O synchronization parameters
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
` (6 preceding siblings ...)
2025-09-05 13:55 ` [PATCH v2 7/9] pinctrl: stm32: Support I/O synchronization parameters Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
2025-09-10 2:10 ` Rob Herring (Arm)
2025-09-05 13:55 ` [PATCH v2 9/9] arm64: dts: st: Add I/O sync to eth2 pinctrl in stm32mp25-pinctrl.dtsi Antonio Borneo
8 siblings, 1 reply; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
Document the support of the I/O synchronization parameters:
- skew-delay;
- skew-delay-direction;
- st,io-sync.
Require 'skew-delay-direction' when 'skew-delay' is non zero.
Allow the new properties only with compatibles that support them.
Add an example that uses all the new properties.
Co-developed-by: Fabien Dessenne <fabien.dessenne@foss.st.com>
Signed-off-by: Fabien Dessenne <fabien.dessenne@foss.st.com>
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
.../bindings/pinctrl/st,stm32-pinctrl.yaml | 92 +++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
index 961161c2ab62b..d20669fd5d9c9 100644
--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
@@ -225,12 +225,82 @@ patternProperties:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3]
+ skew-delay:
+ description: |
+ IO synchronization delay applied to the input or output path
+ depending on 'skew-delay-direction' property
+ 0: No delay
+ 1: Delay 0.30 ns
+ 2: Delay 0.50 ns
+ 3: Delay 0.75 ns
+ 4: Delay 1.00 ns
+ 5: Delay 1.25 ns
+ 6: Delay 1.50 ns
+ 7: Delay 1.75 ns
+ 8: Delay 2.00 ns
+ 9: Delay 2.25 ns
+ 10: Delay 2.50 ns
+ 11: Delay 2.75 ns
+ 12: Delay 3.00 ns
+ 13: Delay 3.25 ns
+ minimum: 0
+ maximum: 13
+ default: 0
+
+ skew-delay-direction:
+ description: |
+ IO synchronization delay path location
+ 1: Delay on the output path
+ 2: Delay on the input path
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [1, 2]
+
+ st,io-sync:
+ description: |
+ IO synchronization through re-sampling or inversion
+ 0: data or clock GPIO pass-through
+ 1: clock GPIO inverted
+ 2: data GPIO re-sampled on clock rising edge
+ 3: data GPIO re-sampled on clock falling edge
+ 4: data GPIO re-sampled on both clock edges
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3, 4]
+ default: 0
+
required:
- pinmux
+ allOf:
+ - if:
+ not:
+ properties:
+ skew-delay:
+ const: 0
+ then:
+ required:
+ - skew-delay-direction
+
allOf:
- $ref: pinctrl.yaml#
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - st,stm32mp257-pinctrl
+ - st,stm32mp257-z-pinctrl
+ then:
+ patternProperties:
+ '-[0-9]*$':
+ patternProperties:
+ '^pins':
+ properties:
+ skew-delay: false
+ skew-delay-direction: false
+ st,io-sync: false
+
required:
- compatible
- '#address-cells'
@@ -311,4 +381,26 @@ examples:
pinctrl-names = "default";
};
+ - |
+ #include <dt-bindings/pinctrl/stm32-pinfunc.h>
+ //Example 4 skew-delay and st,io-sync
+ pinctrl: pinctrl@44240000 {
+ compatible = "st,stm32mp257-pinctrl";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x44240000 0xa0400>;
+
+ eth3_rgmii_pins_a: eth3-rgmii-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('A', 6, AF14)>;
+ st,io-sync = <4>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('H', 2, AF14)>;
+ skew-delay = <2>;
+ skew-delay-direction = <1>;
+ };
+ };
+ };
+
...
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v2 8/9] dt-bindings: pinctrl: stm32: Support I/O synchronization parameters
2025-09-05 13:55 ` [PATCH v2 8/9] dt-bindings: " Antonio Borneo
@ 2025-09-10 2:10 ` Rob Herring (Arm)
0 siblings, 0 replies; 14+ messages in thread
From: Rob Herring (Arm) @ 2025-09-10 2:10 UTC (permalink / raw)
To: Antonio Borneo
Cc: Maxime Coquelin, Valentin Caron, linux-kernel, linux-gpio,
Krzysztof Kozlowski, Linus Walleij, devicetree, Conor Dooley,
Christophe Roullier, Fabien Dessenne, linux-stm32,
Alexandre Torgue, linux-arm-kernel, Bartosz Golaszewski
On Fri, 05 Sep 2025 15:55:46 +0200, Antonio Borneo wrote:
> Document the support of the I/O synchronization parameters:
> - skew-delay;
> - skew-delay-direction;
> - st,io-sync.
>
> Require 'skew-delay-direction' when 'skew-delay' is non zero.
> Allow the new properties only with compatibles that support them.
> Add an example that uses all the new properties.
>
> Co-developed-by: Fabien Dessenne <fabien.dessenne@foss.st.com>
> Signed-off-by: Fabien Dessenne <fabien.dessenne@foss.st.com>
> Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
> ---
> .../bindings/pinctrl/st,stm32-pinctrl.yaml | 92 +++++++++++++++++++
> 1 file changed, 92 insertions(+)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 9/9] arm64: dts: st: Add I/O sync to eth2 pinctrl in stm32mp25-pinctrl.dtsi
2025-09-05 13:55 [PATCH v2 0/9] pinctrl: stm32: Support I/O synchronization Antonio Borneo
` (7 preceding siblings ...)
2025-09-05 13:55 ` [PATCH v2 8/9] dt-bindings: " Antonio Borneo
@ 2025-09-05 13:55 ` Antonio Borneo
8 siblings, 0 replies; 14+ messages in thread
From: Antonio Borneo @ 2025-09-05 13:55 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maxime Coquelin, Alexandre Torgue, Bartosz Golaszewski,
linux-gpio, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel
Cc: Antonio Borneo, Christophe Roullier, Fabien Dessenne,
Valentin Caron
On board stm32mp257f-ev1, the propagation delay between eth2 and
the external PHY requires a compensation to guarantee that no
packet get lost in all the working conditions.
Add I/O synchronization properties in pinctrl on all the RGMII
data pins, activating re-sampling on both edges of the clock.
Co-developed-by: Christophe Roullier <christophe.roullier@foss.st.com>
Signed-off-by: Christophe Roullier <christophe.roullier@foss.st.com>
Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
---
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
index 5ac9e72478ddd..4b4347241e30a 100644
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
@@ -16,6 +16,7 @@ pins1 {
bias-disable;
drive-push-pull;
slew-rate = <3>;
+ st,io-sync = <4>;
};
pins2 {
pinmux = <STM32_PINMUX('F', 8, AF10)>, /* ETH_RGMII_CLK125 */
@@ -38,6 +39,7 @@ pins4 {
<STM32_PINMUX('C', 11, AF10)>, /* ETH_RGMII_RXD3 */
<STM32_PINMUX('C', 3, AF10)>; /* ETH_RGMII_RX_CTL */
bias-disable;
+ st,io-sync = <4>;
};
pins5 {
pinmux = <STM32_PINMUX('F', 6, AF10)>; /* ETH_RGMII_RX_CLK */
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread