SAMA5 Serial: Reading IMR and disabling interrupt must be atomic

This commit is contained in:
Gregory Nutt 2015-04-08 15:27:31 -06:00
parent 35312b31f9
commit a93913c0f4
3 changed files with 31 additions and 14 deletions

View File

@ -650,7 +650,7 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu
static inline void up_restoreusartint(struct up_dev_s *priv, uint32_t imr) static inline void up_restoreusartint(struct up_dev_s *priv, uint32_t imr)
{ {
/* Restore the previous interrupt state */ /* Restore the previous interrupt state (assuming all interrupts disabled) */
up_serialout(priv, SAM_UART_IER_OFFSET, imr); up_serialout(priv, SAM_UART_IER_OFFSET, imr);
} }

View File

@ -727,11 +727,22 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu
putreg32(value, priv->usartbase + offset); putreg32(value, priv->usartbase + offset);
} }
/****************************************************************************
* Name: up_restoreusartint
****************************************************************************/
static inline void up_restoreusartint(struct up_dev_s *priv, uint32_t imr)
{
/* Restore the previous interrupt state (assuming all interrupts disabled) */
up_serialout(priv, SAM_UART_IER_OFFSET, imr);
}
/**************************************************************************** /****************************************************************************
* Name: up_disableallints * Name: up_disableallints
****************************************************************************/ ****************************************************************************/
static void up_disableallints(struct up_dev_s *priv) static void up_disableallints(struct up_dev_s *priv, uint32_t *imr)
{ {
irqstate_t flags; irqstate_t flags;
@ -739,6 +750,13 @@ static void up_disableallints(struct up_dev_s *priv)
flags = irqsave(); flags = irqsave();
/* Return the current interrupt state */
if (imr)
{
*imr = up_serialin(priv, SAM_UART_IMR_OFFSET);
}
/* Disable all interrupts */ /* Disable all interrupts */
up_serialout(priv, SAM_UART_IDR_OFFSET, UART_INT_ALLINTS); up_serialout(priv, SAM_UART_IDR_OFFSET, UART_INT_ALLINTS);
@ -887,7 +905,7 @@ static void up_shutdown(struct uart_dev_s *dev)
/* Disable all interrupts */ /* Disable all interrupts */
up_disableallints(priv); up_disableallints(priv, NULL);
} }
/**************************************************************************** /****************************************************************************
@ -1243,13 +1261,12 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
* implement TCSADRAIN / TCSAFLUSH * implement TCSADRAIN / TCSAFLUSH
*/ */
imr = up_serialin(priv, SAM_UART_IMR_OFFSET); up_disableallints(priv, &imr);
up_disableallints(priv);
ret = up_setup(dev); ret = up_setup(dev);
/* Restore the interrupt state */ /* Restore the interrupt state */
up_serialout(priv, SAM_UART_IER_OFFSET, imr); up_restoreusartint(priv, imr);
} }
} }
break; break;
@ -1437,25 +1454,25 @@ void sam_earlyserialinit(void)
/* Disable all USARTS */ /* Disable all USARTS */
#ifdef TTYS0_DEV #ifdef TTYS0_DEV
up_disableallints(TTYS0_DEV.priv); up_disableallints(TTYS0_DEV.priv, NULL);
#endif #endif
#ifdef TTYS1_DEV #ifdef TTYS1_DEV
up_disableallints(TTYS1_DEV.priv); up_disableallints(TTYS1_DEV.priv, NULL);
#endif #endif
#ifdef TTYS2_DEV #ifdef TTYS2_DEV
up_disableallints(TTYS2_DEV.priv); up_disableallints(TTYS2_DEV.priv, NULL);
#endif #endif
#ifdef TTYS3_DEV #ifdef TTYS3_DEV
up_disableallints(TTYS3_DEV.priv); up_disableallints(TTYS3_DEV.priv, NULL);
#endif #endif
#ifdef TTYS4_DEV #ifdef TTYS4_DEV
up_disableallints(TTYS4_DEV.priv); up_disableallints(TTYS4_DEV.priv, NULL);
#endif #endif
#ifdef TTYS5_DEV #ifdef TTYS5_DEV
up_disableallints(TTYS5_DEV.priv); up_disableallints(TTYS5_DEV.priv, NULL);
#endif #endif
#ifdef TTYS6_DEV #ifdef TTYS6_DEV
up_disableallints(TTYS6_DEV.priv); up_disableallints(TTYS6_DEV.priv, NULL);
#endif #endif
/* Configuration whichever one is the console */ /* Configuration whichever one is the console */

View File

@ -710,7 +710,7 @@ static inline void sam_serialout(struct sam_dev_s *priv, int offset, uint32_t va
static inline void sam_restoreusartint(struct sam_dev_s *priv, uint32_t imr) static inline void sam_restoreusartint(struct sam_dev_s *priv, uint32_t imr)
{ {
/* Restore the previous interrupt state */ /* Restore the previous interrupt state (assuming all interrupts disabled) */
sam_serialout(priv, SAM_UART_IER_OFFSET, imr); sam_serialout(priv, SAM_UART_IER_OFFSET, imr);
} }