diff --git a/arch/arm/src/imx9/imx9_lpuart.c b/arch/arm/src/imx9/imx9_lpuart.c index b3997838181b7..3e35c26ccdb7e 100644 --- a/arch/arm/src/imx9/imx9_lpuart.c +++ b/arch/arm/src/imx9/imx9_lpuart.c @@ -305,6 +305,7 @@ struct imx9_uart_s const bool userts; /* input flow control (RTS) available */ const bool rs485mode; /* We are in RS485 (RTS on TX) mode */ const bool inviflow; /* Invert RTS sense */ + spinlock_t lock; /* Spinlock */ uint32_t baud; /* Configured baud */ uint32_t ie; /* Saved enabled interrupts */ uint8_t irq; /* IRQ associated with this UART */ @@ -627,6 +628,7 @@ static struct imx9_uart_s g_lpuart1priv = .irq = IMX9_IRQ_LPUART1, .parity = CONFIG_LPUART1_PARITY, .bits = CONFIG_LPUART1_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART1_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART1_OFLOWCONTROL) .usects = true, @@ -686,6 +688,7 @@ static struct imx9_uart_s g_lpuart2priv = .irq = IMX9_IRQ_LPUART2, .parity = CONFIG_LPUART2_PARITY, .bits = CONFIG_LPUART2_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART2_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART2_OFLOWCONTROL) .usects = true, @@ -745,6 +748,7 @@ static struct imx9_uart_s g_lpuart3priv = .irq = IMX9_IRQ_LPUART3, .parity = CONFIG_LPUART3_PARITY, .bits = CONFIG_LPUART3_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART3_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART3_OFLOWCONTROL) .usects = true, @@ -804,6 +808,7 @@ static struct imx9_uart_s g_lpuart4priv = .irq = IMX9_IRQ_LPUART4, .parity = CONFIG_LPUART4_PARITY, .bits = CONFIG_LPUART4_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART4_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART4_OFLOWCONTROL) .usects = true, @@ -863,6 +868,7 @@ static struct imx9_uart_s g_lpuart5priv = .irq = IMX9_IRQ_LPUART5, .parity = CONFIG_LPUART5_PARITY, .bits = CONFIG_LPUART5_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART5_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART5_OFLOWCONTROL) .usects = true, @@ -922,6 +928,7 @@ static struct imx9_uart_s g_lpuart6priv = .irq = IMX9_IRQ_LPUART6, .parity = CONFIG_LPUART6_PARITY, .bits = CONFIG_LPUART6_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART6_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART6_OFLOWCONTROL) .usects = true, @@ -981,6 +988,7 @@ static struct imx9_uart_s g_lpuart7priv = .irq = IMX9_IRQ_LPUART7, .parity = CONFIG_LPUART7_PARITY, .bits = CONFIG_LPUART7_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART7_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART7_OFLOWCONTROL) .usects = true, @@ -1040,6 +1048,7 @@ static struct imx9_uart_s g_lpuart8priv = .irq = IMX9_IRQ_LPUART8, .parity = CONFIG_LPUART8_PARITY, .bits = CONFIG_LPUART8_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART8_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART8_OFLOWCONTROL) .usects = true, @@ -1122,13 +1131,11 @@ static int imx9_dma_nextrx(struct imx9_uart_s *priv) * Name: imx9_disableuartint ****************************************************************************/ -static inline void imx9_disableuartint(struct imx9_uart_s *priv, - uint32_t *ie) +static inline void imx9_disableuartint_nolock(struct imx9_uart_s *priv, + uint32_t *ie) { - irqstate_t flags; uint32_t regval; - flags = spin_lock_irqsave(NULL); regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); /* Return the current Rx and Tx interrupt state */ @@ -1140,29 +1147,45 @@ static inline void imx9_disableuartint(struct imx9_uart_s *priv, regval &= ~LPUART_ALL_INTS; imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); +} + +static inline void imx9_disableuartint(struct imx9_uart_s *priv, + uint32_t *ie) +{ + irqstate_t flags; + + flags = spin_lock_irqsave(&priv->lock); + imx9_disableuartint_nolock(priv, ie); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** * Name: imx9_restoreuartint ****************************************************************************/ +static inline void imx9_restoreuartint_nolock(struct imx9_uart_s *priv, + uint32_t ie) +{ + uint32_t regval; + + regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); + regval &= ~LPUART_ALL_INTS; + regval |= ie; + imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); +} + static inline void imx9_restoreuartint(struct imx9_uart_s *priv, - uint32_t ie) + uint32_t ie) { irqstate_t flags; - uint32_t regval; /* Enable/disable any interrupts that are currently disabled but should be * enabled/disabled. */ - flags = spin_lock_irqsave(NULL); - regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); - regval &= ~LPUART_ALL_INTS; - regval |= ie; - imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&priv->lock); + imx9_restoreuartint_nolock(priv, ie); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -1759,15 +1782,15 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) * implement TCSADRAIN / TCSAFLUSH */ - flags = spin_lock_irqsave(NULL); - imx9_disableuartint(priv, &ie); + flags = spin_lock_irqsave(&priv->lock); + imx9_disableuartint_nolock(priv, &ie); ret = dev->ops->setup(dev); /* Restore the interrupt state */ - imx9_restoreuartint(priv, ie); + imx9_restoreuartint_nolock(priv, ie); priv->ie = ie; - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } } break; @@ -1779,8 +1802,8 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) uint32_t regval; struct imx9_uart_s *priv = (struct imx9_uart_s *)dev; - flags = spin_lock_irqsave(NULL); - regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); + flags = spin_lock_irqsave(&priv->lock); + regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); if ((arg & SER_SINGLEWIRE_ENABLED) != 0) { @@ -1793,7 +1816,7 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } break; #endif @@ -1806,7 +1829,7 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) uint32_t regval; struct imx9_uart_s *priv = (struct imx9_uart_s *)dev; - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); ctrl = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); stat = imx9_serialin(priv, IMX9_LPUART_STAT_OFFSET); regval = ctrl; @@ -1845,7 +1868,7 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) imx9_serialout(priv, IMX9_LPUART_STAT_OFFSET, stat); imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, ctrl); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } break; #endif @@ -1899,7 +1922,7 @@ static void imx9_rxint(struct uart_dev_s *dev, bool enable) /* Enable interrupts for data available at Rx */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); if (enable) { #ifndef CONFIG_SUPPRESS_SERIAL_INTS @@ -1915,7 +1938,7 @@ static void imx9_rxint(struct uart_dev_s *dev, bool enable) regval &= ~LPUART_ALL_INTS; regval |= priv->ie; imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } #endif @@ -2320,7 +2343,7 @@ static void imx9_txint(struct uart_dev_s *dev, bool enable) /* Enable interrupt for TX complete */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); if (enable) { #ifndef CONFIG_SUPPRESS_SERIAL_INTS @@ -2336,7 +2359,7 @@ static void imx9_txint(struct uart_dev_s *dev, bool enable) regval &= ~LPUART_ALL_INTS; regval |= priv->ie; imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } #endif diff --git a/arch/arm64/src/imx9/imx9_lpuart.c b/arch/arm64/src/imx9/imx9_lpuart.c index c473d241c3830..d8352a56459c3 100644 --- a/arch/arm64/src/imx9/imx9_lpuart.c +++ b/arch/arm64/src/imx9/imx9_lpuart.c @@ -304,6 +304,7 @@ struct imx9_uart_s const bool userts; /* input flow control (RTS) available */ const bool rs485mode; /* We are in RS485 (RTS on TX) mode */ const bool inviflow; /* Invert RTS sense */ + spinlock_t lock; /* Spinlock */ uint32_t baud; /* Configured baud */ uint32_t ie; /* Saved enabled interrupts */ uint8_t irq; /* IRQ associated with this UART */ @@ -626,6 +627,7 @@ static struct imx9_uart_s g_lpuart1priv = .irq = IMX9_IRQ_LPUART1, .parity = CONFIG_LPUART1_PARITY, .bits = CONFIG_LPUART1_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART1_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART1_OFLOWCONTROL) .usects = true, @@ -685,6 +687,7 @@ static struct imx9_uart_s g_lpuart2priv = .irq = IMX9_IRQ_LPUART2, .parity = CONFIG_LPUART2_PARITY, .bits = CONFIG_LPUART2_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART2_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART2_OFLOWCONTROL) .usects = true, @@ -744,6 +747,7 @@ static struct imx9_uart_s g_lpuart3priv = .irq = IMX9_IRQ_LPUART3, .parity = CONFIG_LPUART3_PARITY, .bits = CONFIG_LPUART3_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART3_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART3_OFLOWCONTROL) .usects = true, @@ -803,6 +807,7 @@ static struct imx9_uart_s g_lpuart4priv = .irq = IMX9_IRQ_LPUART4, .parity = CONFIG_LPUART4_PARITY, .bits = CONFIG_LPUART4_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART4_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART4_OFLOWCONTROL) .usects = true, @@ -862,6 +867,7 @@ static struct imx9_uart_s g_lpuart5priv = .irq = IMX9_IRQ_LPUART5, .parity = CONFIG_LPUART5_PARITY, .bits = CONFIG_LPUART5_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART5_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART5_OFLOWCONTROL) .usects = true, @@ -921,6 +927,7 @@ static struct imx9_uart_s g_lpuart6priv = .irq = IMX9_IRQ_LPUART6, .parity = CONFIG_LPUART6_PARITY, .bits = CONFIG_LPUART6_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART6_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART6_OFLOWCONTROL) .usects = true, @@ -980,6 +987,7 @@ static struct imx9_uart_s g_lpuart7priv = .irq = IMX9_IRQ_LPUART7, .parity = CONFIG_LPUART7_PARITY, .bits = CONFIG_LPUART7_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART7_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART7_OFLOWCONTROL) .usects = true, @@ -1039,6 +1047,7 @@ static struct imx9_uart_s g_lpuart8priv = .irq = IMX9_IRQ_LPUART8, .parity = CONFIG_LPUART8_PARITY, .bits = CONFIG_LPUART8_BITS, + .lock = SP_UNLOCKED, .stopbits2 = CONFIG_LPUART8_2STOP, # if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART8_OFLOWCONTROL) .usects = true, @@ -1121,13 +1130,11 @@ static int imx9_dma_nextrx(struct imx9_uart_s *priv) * Name: imx9_disableuartint ****************************************************************************/ -static inline void imx9_disableuartint(struct imx9_uart_s *priv, - uint32_t *ie) +static inline void imx9_disableuartint_nolock(struct imx9_uart_s *priv, + uint32_t *ie) { - irqstate_t flags; uint32_t regval; - flags = spin_lock_irqsave(NULL); regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); /* Return the current Rx and Tx interrupt state */ @@ -1139,29 +1146,45 @@ static inline void imx9_disableuartint(struct imx9_uart_s *priv, regval &= ~LPUART_ALL_INTS; imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); +} + +static inline void imx9_disableuartint(struct imx9_uart_s *priv, + uint32_t *ie) +{ + irqstate_t flags; + + flags = spin_lock_irqsave(&priv->lock); + imx9_disableuartint_nolock(priv, ie); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** * Name: imx9_restoreuartint ****************************************************************************/ +static inline void imx9_restoreuartint_nolock(struct imx9_uart_s *priv, + uint32_t ie) +{ + uint32_t regval; + + regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); + regval &= ~LPUART_ALL_INTS; + regval |= ie; + imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); +} + static inline void imx9_restoreuartint(struct imx9_uart_s *priv, - uint32_t ie) + uint32_t ie) { irqstate_t flags; - uint32_t regval; /* Enable/disable any interrupts that are currently disabled but should be * enabled/disabled. */ - flags = spin_lock_irqsave(NULL); - regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); - regval &= ~LPUART_ALL_INTS; - regval |= ie; - imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&priv->lock); + imx9_restoreuartint_nolock(priv, ie); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -1758,15 +1781,15 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) * implement TCSADRAIN / TCSAFLUSH */ - flags = spin_lock_irqsave(NULL); - imx9_disableuartint(priv, &ie); + flags = spin_lock_irqsave(&priv->lock); + imx9_disableuartint_nolock(priv, &ie); ret = dev->ops->setup(dev); /* Restore the interrupt state */ - imx9_restoreuartint(priv, ie); + imx9_restoreuartint_nolock(priv, ie); priv->ie = ie; - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } } break; @@ -1778,8 +1801,8 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) uint32_t regval; struct imx9_uart_s *priv = (struct imx9_uart_s *)dev; - flags = spin_lock_irqsave(NULL); - regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); + flags = spin_lock_irqsave(&priv->lock); + regval = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); if ((arg & SER_SINGLEWIRE_ENABLED) != 0) { @@ -1792,7 +1815,7 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } break; #endif @@ -1805,7 +1828,7 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) uint32_t regval; struct imx9_uart_s *priv = (struct imx9_uart_s *)dev; - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); ctrl = imx9_serialin(priv, IMX9_LPUART_CTRL_OFFSET); stat = imx9_serialin(priv, IMX9_LPUART_STAT_OFFSET); regval = ctrl; @@ -1844,7 +1867,7 @@ static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) imx9_serialout(priv, IMX9_LPUART_STAT_OFFSET, stat); imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, ctrl); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } break; #endif @@ -1898,7 +1921,7 @@ static void imx9_rxint(struct uart_dev_s *dev, bool enable) /* Enable interrupts for data available at Rx */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); if (enable) { #ifndef CONFIG_SUPPRESS_SERIAL_INTS @@ -1914,7 +1937,7 @@ static void imx9_rxint(struct uart_dev_s *dev, bool enable) regval &= ~LPUART_ALL_INTS; regval |= priv->ie; imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } #endif @@ -2319,7 +2342,7 @@ static void imx9_txint(struct uart_dev_s *dev, bool enable) /* Enable interrupt for TX complete */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); if (enable) { #ifndef CONFIG_SUPPRESS_SERIAL_INTS @@ -2335,7 +2358,7 @@ static void imx9_txint(struct uart_dev_s *dev, bool enable) regval &= ~LPUART_ALL_INTS; regval |= priv->ie; imx9_serialout(priv, IMX9_LPUART_CTRL_OFFSET, regval); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } #endif