Skip to content

Commit

Permalink
imxrt: lpuart singlewire transfer support
Browse files Browse the repository at this point in the history
  • Loading branch information
PetervdPerk-NXP committed May 10, 2024
1 parent a35b2a5 commit 82f5fe5
Showing 1 changed file with 110 additions and 1 deletion.
111 changes: 110 additions & 1 deletion arch/arm/src/imxrt/imxrt_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ struct imxrt_uart_s
#endif
#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
const uint32_t tx_gpio; /* TX GPIO pin configuration */
const struct uart_ops_s *prev_ops;
#endif

uint8_t stopbits2:1; /* 1: Configure with 2 stop bits vs 1 */
Expand Down Expand Up @@ -806,11 +807,17 @@ static bool imxrt_rxavailable(struct uart_dev_s *dev);
#if !defined(SERIAL_HAVE_ONLY_TXDMA)
static void imxrt_txint(struct uart_dev_s *dev, bool enable);
#endif
#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
static void imxrt_singlewire_txint(struct uart_dev_s *dev, bool enable);
#endif

#ifdef CONFIG_SERIAL_IFLOWCONTROL
static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
unsigned int nbuffered, bool upper);
#endif
#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
static void imxrt_singlewire_send(struct uart_dev_s *dev, int ch);
#endif
static void imxrt_send(struct uart_dev_s *dev, int ch);

static bool imxrt_txready(struct uart_dev_s *dev);
Expand Down Expand Up @@ -855,6 +862,27 @@ static int up_pm_prepare(struct pm_callback_s *cb, int domain,

/* Serial driver UART operations */

#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
static const struct uart_ops_s g_lpuart_singlewire_ops =
{
.setup = imxrt_setup,
.shutdown = imxrt_shutdown,
.attach = imxrt_attach,
.detach = imxrt_detach,
.ioctl = imxrt_ioctl,
.receive = imxrt_receive,
.rxint = imxrt_rxint,
.rxavailable = imxrt_rxavailable,
#ifdef CONFIG_SERIAL_IFLOWCONTROL
.rxflowcontrol = imxrt_rxflowcontrol,
#endif
.send = imxrt_singlewire_send,
.txint = imxrt_singlewire_txint,
.txready = imxrt_txready,
.txempty = imxrt_txempty,
};
#endif

#if !defined(SERIAL_HAVE_ONLY_TXDMA) && !defined(SERIAL_HAVE_ONLY_RXDMA)
static const struct uart_ops_s g_lpuart_ops =
{
Expand Down Expand Up @@ -2629,7 +2657,9 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)

if ((arg & SER_SINGLEWIRE_ENABLED) != 0)
{
uint32_t gpio_val = IOMUX_OPENDRAIN;
uint32_t gpio_val = (arg & SER_SINGLEWIRE_PUSHPULL) ==
SER_SINGLEWIRE_PUSHPULL ?
IOMUX_CMOS_OUTPUT : IOMUX_OPENDRAIN;
gpio_val |= (arg & SER_SINGLEWIRE_PULL_MASK) ==
SER_SINGLEWIRE_PULLUP ?
IOMUX_PULL_UP : IOMUX_PULL_NONE;
Expand All @@ -2639,13 +2669,19 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
imxrt_config_gpio((priv->tx_gpio &
~(IOMUX_PULL_MASK | IOMUX_OPENDRAIN)) | gpio_val);
regval |= LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC;
priv->prev_ops = priv->dev.ops;
priv->dev.ops = &g_lpuart_singlewire_ops;
}
else
{
imxrt_config_gpio((priv->tx_gpio & ~(IOMUX_PULL_MASK |
IOMUX_OPENDRAIN)) |
IOMUX_PULL_NONE);
regval &= ~(LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC);
if (priv->dev.ops == &g_lpuart_singlewire_ops)
{
priv->dev.ops = priv->prev_ops;
}
}

imxrt_serialout(priv, IMXRT_LPUART_CTRL_OFFSET, regval);
Expand Down Expand Up @@ -3206,6 +3242,34 @@ static void imxrt_dma_send(struct uart_dev_s *dev)
}
#endif

#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
/****************************************************************************
* Name: imxrt_singlewire_send
*
* Description:
* This method will will switch TXDIR to an output
* and send one byte on the UART
*
****************************************************************************/

static void imxrt_singlewire_send(struct uart_dev_s *dev, int ch)
{
struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
uint32_t regval;
irqstate_t flags;

flags = spin_lock_irqsave(NULL);
regval = imxrt_serialin(priv, IMXRT_LPUART_CTRL_OFFSET);
regval &= ~(LPUART_CTRL_RSRC);
regval |= (LPUART_CTRL_TXDIR);
imxrt_serialout(priv, IMXRT_LPUART_CTRL_OFFSET, regval);
spin_unlock_irqrestore(NULL, flags);

imxrt_serialout(priv, IMXRT_LPUART_DATA_OFFSET, (uint32_t)ch);
}

#endif

/****************************************************************************
* Name: imxrt_send
*
Expand Down Expand Up @@ -3279,6 +3343,51 @@ static void imxrt_txint(struct uart_dev_s *dev, bool enable)
}
#endif

/****************************************************************************
* Name: imxrt_singlewire_txint
*
* Description:
* Call to enable or disable TX interrupts in single wire mode
*
****************************************************************************/

#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
static void imxrt_singlewire_txint(struct uart_dev_s *dev, bool enable)
{
struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
irqstate_t flags;
uint32_t regval;

/* Enable interrupt for TX complete */

flags = spin_lock_irqsave(NULL);
regval = imxrt_serialin(priv, IMXRT_LPUART_CTRL_OFFSET);
if (enable)
{
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
priv->ie |= LPUART_CTRL_TIE;
#endif
}
else
{
/* Don't disable TX interrupt yet if transmission isn't complete */

if (imxrt_txempty(dev))
{
regval |= LPUART_CTRL_RSRC;
regval &= ~(LPUART_CTRL_TXDIR);
priv->ie &= ~LPUART_CTRL_TIE;
}
}

regval &= ~LPUART_ALL_INTS;
regval |= priv->ie;

imxrt_serialout(priv, IMXRT_LPUART_CTRL_OFFSET, regval);
spin_unlock_irqrestore(NULL, flags);
}
#endif

/****************************************************************************
* Name: imxrt_txready
*
Expand Down

0 comments on commit 82f5fe5

Please sign in to comment.