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); + 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 }, { } }; -- 2.43.0

