On 2/24/26 10:44, Patrick DELAUNAY wrote:
> Hi,
>
> On 2/5/26 09:07, Patrice Chotard wrote:
>> From: Fabien Dessenne <[email protected]>
>>
>> Support the following IO synchronization parameters:
>> - Delay (in ns)
>> - Delay path (input / output)
>> - Clock edge (single / double edge)
>> - Clock inversion
>> - Retiming
>> These settings allow a fine tuning of the high speed interface signals.
>>
>> Enable this feature for the stm32mp257 SOC.
>>
>> Signed-off-by: Fabien Dessenne <[email protected]>
>> Signed-off-by: Valentin Caron <[email protected]>
>> Signed-off-by: Patrice Chotard <[email protected]>
>> ---
>> drivers/gpio/stm32_gpio_priv.h | 58 +++++++++++++++++++++++++++---
>> drivers/pinctrl/pinctrl_stm32.c | 80
>> +++++++++++++++++++++++++++++++++--------
>> 2 files changed, 119 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/gpio/stm32_gpio_priv.h b/drivers/gpio/stm32_gpio_priv.h
>> index d89e9b8ed60..69868787af0 100644
>> --- a/drivers/gpio/stm32_gpio_priv.h
>> +++ b/drivers/gpio/stm32_gpio_priv.h
>> @@ -51,7 +51,45 @@ enum stm32_gpio_af {
>> STM32_GPIO_AF15
>> };
>> +enum stm32_gpio_delay_path {
>> + STM32_GPIO_DELAY_PATH_OUT = 0,
>> + STM32_GPIO_DELAY_PATH_IN
>> +};
>> +
>> +enum stm32_gpio_clk_edge {
>> + STM32_GPIO_CLK_EDGE_SINGLE = 0,
>> + STM32_GPIO_CLK_EDGE_DOUBLE
>> +};
>> +
>> +enum stm32_gpio_clk_type {
>> + STM32_GPIO_CLK_TYPE_NOT_INVERT = 0,
>> + STM32_GPIO_CLK_TYPE_INVERT
>> +};
>> +
>> +enum stm32_gpio_retime {
>> + STM32_GPIO_RETIME_DISABLED = 0,
>> + STM32_GPIO_RETIME_ENABLED
>> +};
>> +
>> +enum stm32_gpio_delay {
>> + STM32_GPIO_DELAY_NONE = 0,
>> + STM32_GPIO_DELAY_0_3,
>> + STM32_GPIO_DELAY_0_5,
>> + STM32_GPIO_DELAY_0_75,
>> + STM32_GPIO_DELAY_1_0,
>> + STM32_GPIO_DELAY_1_25,
>> + STM32_GPIO_DELAY_1_5,
>> + STM32_GPIO_DELAY_1_75,
>> + STM32_GPIO_DELAY_2_0,
>> + STM32_GPIO_DELAY_2_25,
>> + STM32_GPIO_DELAY_2_5,
>> + STM32_GPIO_DELAY_2_75,
>> + STM32_GPIO_DELAY_3_0,
>> + STM32_GPIO_DELAY_3_25
>> +};
>> +
>> #define STM32_GPIO_FLAG_SEC_CTRL BIT(0)
>> +#define STM32_GPIO_FLAG_IO_SYNC_CTRL BIT(1)
>> struct stm32_gpio_dsc {
>> u8 port;
>> @@ -59,11 +97,16 @@ struct stm32_gpio_dsc {
>> };
>> struct stm32_gpio_ctl {
>> - enum stm32_gpio_mode mode;
>> - enum stm32_gpio_otype otype;
>> - enum stm32_gpio_speed speed;
>> - enum stm32_gpio_pupd pupd;
>> - enum stm32_gpio_af af;
>> + enum stm32_gpio_mode mode;
>> + enum stm32_gpio_otype otype;
>> + enum stm32_gpio_speed speed;
>> + enum stm32_gpio_pupd pupd;
>> + enum stm32_gpio_af af;
>> + enum stm32_gpio_delay_path delay_path;
>> + enum stm32_gpio_clk_edge clk_edge;
>> + enum stm32_gpio_clk_type clk_type;
>> + enum stm32_gpio_retime retime;
>> + enum stm32_gpio_delay delay;
>> };
>> struct stm32_gpio_regs {
>> @@ -79,6 +122,11 @@ struct stm32_gpio_regs {
>> u32 brr; /* GPIO port bit reset */
>> u32 rfu; /* Reserved */
>> u32 seccfgr; /* GPIO secure configuration */
>> + u32 rfu2; /* Reserved (privcfgr) */
>> + u32 rfu3; /* Reserved (rcfglock) */
>> + u32 rfu4; /* Reserved */
>> + u32 delayr[2]; /* GPIO port delay */
>> + u32 advcfgr[2]; /* GPIO port PIO control */
>> };
>> struct stm32_gpio_priv {
>> diff --git a/drivers/pinctrl/pinctrl_stm32.c
>> b/drivers/pinctrl/pinctrl_stm32.c
>> index 1758f9a909c..7d5a0471a65 100644
>> --- a/drivers/pinctrl/pinctrl_stm32.c
>> +++ b/drivers/pinctrl/pinctrl_stm32.c
>> @@ -29,6 +29,12 @@
>> #define OTYPE_MSK 1
>> #define AFR_MASK 0xF
>> #define SECCFG_MSK 1
>> +#define ADVCFGR_MASK 0xF
>> +#define DELAYR_MASK 0xF
>> +#define ADVCFGR_DLYPATH_POS 0
>> +#define ADVCFGR_DE_POS 1
>> +#define ADVCFGR_INVCLK_POS 2
>> +#define ADVCFGR_RET_POS 3
>> struct stm32_pinctrl_priv {
>> struct hwspinlock hws;
>> @@ -43,6 +49,7 @@ struct stm32_gpio_bank {
>> struct stm32_pinctrl_data {
>> bool secure_control;
>> + bool io_sync_control;
>> };
>> #ifndef CONFIG_XPL_BUILD
>> @@ -304,7 +311,7 @@ static int stm32_gpio_config(ofnode node,
>> struct stm32_gpio_regs *regs = priv->regs;
>> struct stm32_pinctrl_priv *ctrl_priv;
>> int ret;
>> - u32 index;
>> + u32 index, io_sync, advcfg;
>> /* Check access protection */
>> ret = stm32_pinctrl_get_access(desc->dev, desc->offset);
>> @@ -318,6 +325,14 @@ static int stm32_gpio_config(ofnode node,
>> ctl->pupd > 2 || ctl->speed > 3)
>> return -EINVAL;
>> + io_sync = dev_get_driver_data(desc->dev) &
>> STM32_GPIO_FLAG_IO_SYNC_CTRL;
>> + if (io_sync && (ctl->delay_path > STM32_GPIO_DELAY_PATH_IN ||
>> + ctl->clk_edge > STM32_GPIO_CLK_EDGE_DOUBLE ||
>> + ctl->clk_type > STM32_GPIO_CLK_TYPE_INVERT ||
>> + ctl->retime > STM32_GPIO_RETIME_ENABLED ||
>> + ctl->delay > STM32_GPIO_DELAY_3_25))
>> + return -EINVAL;
>> +
>> ctrl_priv = dev_get_priv(dev_get_parent(desc->dev));
>> ret = hwspinlock_lock_timeout(&ctrl_priv->hws, 10);
>> if (ret == -ETIME) {
>> @@ -339,6 +354,20 @@ static int stm32_gpio_config(ofnode node,
>> index = desc->offset;
>> clrsetbits_le32(®s->otyper, OTYPE_MSK << index, ctl->otype <<
>> index);
>> + if (io_sync) {
>> + index = (desc->offset & 0x07) * 4;
>> + advcfg = (ctl->delay_path << ADVCFGR_DLYPATH_POS) |
>> + (ctl->clk_edge << ADVCFGR_DE_POS) |
>> + (ctl->clk_type << ADVCFGR_INVCLK_POS) |
>> + (ctl->retime << ADVCFGR_RET_POS);
>> +
>> + clrsetbits_le32(®s->advcfgr[desc->offset >> 3],
>> + ADVCFGR_MASK << index, advcfg << index);
>> +
>> + clrsetbits_le32(®s->delayr[desc->offset >> 3],
>> + DELAYR_MASK << index, ctl->delay << index);
>> + }
>> +
>> uc_priv->name[desc->offset] = strdup(ofnode_get_name(node));
>> hwspinlock_unlock(&ctrl_priv->hws);
>> @@ -391,10 +420,24 @@ static int prep_gpio_ctl(struct stm32_gpio_ctl
>> *gpio_ctl, u32 gpio_fn,
>> else
>> gpio_ctl->pupd = STM32_GPIO_PUPD_NO;
>> + gpio_ctl->delay_path = ofnode_read_u32_default(node,
>> "st,io-delay-path", 0);
>> + gpio_ctl->clk_edge = ofnode_read_u32_default(node, "st,io-clk-edge", 0);
>> + gpio_ctl->clk_type = ofnode_read_u32_default(node, "st,io-clk-type", 0);
>> + gpio_ctl->retime = ofnode_read_u32_default(node, "st,io-retime", 0);
>> + gpio_ctl->delay = ofnode_read_u32_default(node, "st,io-delay", 0);
>> +
>
>
> The binding seens not aligned with latest proposal done for kernel
>
> https://patchwork.ozlabs.org/project/devicetree-bindings/list/?series=479156
>
>
> 'skew-delay-{in,out}put-ps'
>
>
> https://patchwork.ozlabs.org/project/devicetree-bindings/patch/[email protected]/
>
>
> I think, it is the old OpenSTLinux downstream binding
Hi Patrick
Good catch, you are right, i wasn't aware of bindings update on kernel's side
uypstream vs downstrem.
I will drop this patch and resubmit an update later.
Thanks
Patrice
>
>
>> log_debug("gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is =
>> %x\n",
>> gpio_fn, gpio_ctl->speed, gpio_ctl->otype,
>> gpio_ctl->pupd);
>> + if (gpio_ctl->retime || gpio_ctl->clk_type || gpio_ctl->clk_edge ||
>> gpio_ctl->delay_path ||
>> + gpio_ctl->delay)
>> + log_debug(" Retime:%d InvClk:%d DblEdge:%d DelayIn:%d\n",
>> + gpio_ctl->retime, gpio_ctl->clk_type, gpio_ctl->clk_edge,
>> + gpio_ctl->delay_path);
>> + if (gpio_ctl->delay)
>> + log_debug(" Delay: %d (%d ps)\n", gpio_ctl->delay,
>> gpio_ctl->delay * 250);
>> +
>> return 0;
>> }
>> @@ -466,7 +509,9 @@ static int stm32_pinctrl_bind(struct udevice *dev)
>> return -EINVAL;
>> }
>> if (drv_data->secure_control)
>> - gpio_data = STM32_GPIO_FLAG_SEC_CTRL;
>> + gpio_data |= STM32_GPIO_FLAG_SEC_CTRL;
>> + if (drv_data->io_sync_control)
>> + gpio_data |= STM32_GPIO_FLAG_IO_SYNC_CTRL;
>> dev_for_each_subnode(node, dev) {
>> dev_dbg(dev, "bind %s\n", ofnode_get_name(node));
>> @@ -546,25 +591,32 @@ static struct pinctrl_ops stm32_pinctrl_ops = {
>> #endif
>> };
>> -static const struct stm32_pinctrl_data stm32_pinctrl_no_sec = {
>> +static const struct stm32_pinctrl_data stm32_pinctrl_base = {
>> .secure_control = false,
>> + .io_sync_control = false,
>> +};
>> +
>> +static const struct stm32_pinctrl_data stm32_pinctrl_sec = {
>> + .secure_control = true,
>> + .io_sync_control = false,
>> };
>> -static const struct stm32_pinctrl_data stm32_pinctrl_with_sec = {
>> +static const struct stm32_pinctrl_data stm32_pinctrl_sec_iosync = {
>> .secure_control = true,
>> + .io_sync_control = true,
>> };
>> static const struct udevice_id stm32_pinctrl_ids[] = {
>> - { .compatible = "st,stm32f429-pinctrl", .data =
>> (ulong)&stm32_pinctrl_no_sec },
>> - { .compatible = "st,stm32f469-pinctrl", .data =
>> (ulong)&stm32_pinctrl_no_sec },
>> - { .compatible = "st,stm32f746-pinctrl", .data =
>> (ulong)&stm32_pinctrl_no_sec },
>> - { .compatible = "st,stm32f769-pinctrl", .data =
>> (ulong)&stm32_pinctrl_no_sec },
>> - { .compatible = "st,stm32h743-pinctrl", .data =
>> (ulong)&stm32_pinctrl_no_sec },
>> - { .compatible = "st,stm32mp157-pinctrl", .data =
>> (ulong)&stm32_pinctrl_no_sec },
>> - { .compatible = "st,stm32mp157-z-pinctrl", .data =
>> (ulong)&stm32_pinctrl_no_sec },
>> - { .compatible = "st,stm32mp135-pinctrl", .data =
>> (ulong)&stm32_pinctrl_with_sec },
>> - { .compatible = "st,stm32mp257-pinctrl", .data =
>> (ulong)&stm32_pinctrl_with_sec },
>> - { .compatible = "st,stm32mp257-z-pinctrl", .data =
>> (ulong)&stm32_pinctrl_with_sec },
>> + { .compatible = "st,stm32f429-pinctrl", .data =
>> (ulong)&stm32_pinctrl_base },
>> + { .compatible = "st,stm32f469-pinctrl", .data =
>> (ulong)&stm32_pinctrl_base },
>> + { .compatible = "st,stm32f746-pinctrl", .data =
>> (ulong)&stm32_pinctrl_base },
>> + { .compatible = "st,stm32f769-pinctrl", .data =
>> (ulong)&stm32_pinctrl_base },
>> + { .compatible = "st,stm32h743-pinctrl", .data =
>> (ulong)&stm32_pinctrl_base },
>> + { .compatible = "st,stm32mp157-pinctrl", .data =
>> (ulong)&stm32_pinctrl_base },
>> + { .compatible = "st,stm32mp157-z-pinctrl", .data =
>> (ulong)&stm32_pinctrl_base },
>> + { .compatible = "st,stm32mp135-pinctrl", .data =
>> (ulong)&stm32_pinctrl_sec },
>> + { .compatible = "st,stm32mp257-pinctrl", .data =
>> (ulong)&stm32_pinctrl_sec_iosync },
>> + { .compatible = "st,stm32mp257-z-pinctrl", .data =
>> (ulong)&stm32_pinctrl_sec_iosync },
>> { }
>> };
>>
> Thanks
>
> Patrick
>