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(&regs->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(&regs->advcfgr[desc->offset >> 3],
+                               ADVCFGR_MASK << index, advcfg << index);
+
+               clrsetbits_le32(&regs->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

Reply via email to