imxrt: lpuart singlewire transfer support
This commit is contained in:
parent
975d99c3f6
commit
a8f81e4051
@ -743,6 +743,7 @@ struct imxrt_uart_s
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
|
#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
|
||||||
const uint32_t tx_gpio; /* TX GPIO pin configuration */
|
const uint32_t tx_gpio; /* TX GPIO pin configuration */
|
||||||
|
const struct uart_ops_s *prev_ops;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t stopbits2:1; /* 1: Configure with 2 stop bits vs 1 */
|
uint8_t stopbits2:1; /* 1: Configure with 2 stop bits vs 1 */
|
||||||
@ -806,11 +807,17 @@ static bool imxrt_rxavailable(struct uart_dev_s *dev);
|
|||||||
#if !defined(SERIAL_HAVE_ONLY_TXDMA)
|
#if !defined(SERIAL_HAVE_ONLY_TXDMA)
|
||||||
static void imxrt_txint(struct uart_dev_s *dev, bool enable);
|
static void imxrt_txint(struct uart_dev_s *dev, bool enable);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
|
||||||
|
static void imxrt_singlewire_txint(struct uart_dev_s *dev, bool enable);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
|
static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
|
||||||
unsigned int nbuffered, bool upper);
|
unsigned int nbuffered, bool upper);
|
||||||
#endif
|
#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 void imxrt_send(struct uart_dev_s *dev, int ch);
|
||||||
|
|
||||||
static bool imxrt_txready(struct uart_dev_s *dev);
|
static bool imxrt_txready(struct uart_dev_s *dev);
|
||||||
@ -855,6 +862,27 @@ static int up_pm_prepare(struct pm_callback_s *cb, int domain,
|
|||||||
|
|
||||||
/* Serial driver UART operations */
|
/* 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)
|
#if !defined(SERIAL_HAVE_ONLY_TXDMA) && !defined(SERIAL_HAVE_ONLY_RXDMA)
|
||||||
static const struct uart_ops_s g_lpuart_ops =
|
static const struct uart_ops_s g_lpuart_ops =
|
||||||
{
|
{
|
||||||
@ -2629,7 +2657,9 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
if ((arg & SER_SINGLEWIRE_ENABLED) != 0)
|
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) ==
|
gpio_val |= (arg & SER_SINGLEWIRE_PULL_MASK) ==
|
||||||
SER_SINGLEWIRE_PULLUP ?
|
SER_SINGLEWIRE_PULLUP ?
|
||||||
IOMUX_PULL_UP : IOMUX_PULL_NONE;
|
IOMUX_PULL_UP : IOMUX_PULL_NONE;
|
||||||
@ -2639,6 +2669,8 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
|
|||||||
imxrt_config_gpio((priv->tx_gpio &
|
imxrt_config_gpio((priv->tx_gpio &
|
||||||
~(IOMUX_PULL_MASK | IOMUX_OPENDRAIN)) | gpio_val);
|
~(IOMUX_PULL_MASK | IOMUX_OPENDRAIN)) | gpio_val);
|
||||||
regval |= LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC;
|
regval |= LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC;
|
||||||
|
priv->prev_ops = priv->dev.ops;
|
||||||
|
priv->dev.ops = &g_lpuart_singlewire_ops;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2646,6 +2678,10 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
|
|||||||
IOMUX_OPENDRAIN)) |
|
IOMUX_OPENDRAIN)) |
|
||||||
IOMUX_PULL_NONE);
|
IOMUX_PULL_NONE);
|
||||||
regval &= ~(LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC);
|
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);
|
imxrt_serialout(priv, IMXRT_LPUART_CTRL_OFFSET, regval);
|
||||||
@ -3206,6 +3242,34 @@ static void imxrt_dma_send(struct uart_dev_s *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
* Name: imxrt_send
|
||||||
*
|
*
|
||||||
@ -3279,6 +3343,51 @@ static void imxrt_txint(struct uart_dev_s *dev, bool enable)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
* Name: imxrt_txready
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user