diff mbox series

serial: imx: leave IRTS disabled if using modem-control CTS

Message ID 20220214213020.685-1-tharvey@gateworks.com
State New
Headers show
Series serial: imx: leave IRTS disabled if using modem-control CTS | expand

Commit Message

Tim Harvey Feb. 14, 2022, 9:30 p.m. UTC
If using modem-control gpios for CTS we must leave IRTS disabled
as otherwise the hardware will only transmit based on the internal RTS
pin routed to it.

This allows hardware flow control to be used with cts-gpios.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 drivers/tty/serial/imx.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Tomasz Moń Feb. 15, 2022, 6:03 a.m. UTC | #1
On 14.02.2022 22:30, Tim Harvey wrote:
> If using modem-control gpios for CTS we must leave IRTS disabled
> as otherwise the hardware will only transmit based on the internal RTS
> pin routed to it.
> 
> This allows hardware flow control to be used with cts-gpios.

This hardware flow control sounds quite limited. Once CTS becomes
inactive, the transmitter will still output all characters from TxFIFO.
Transmitting whole TxFIFO already sounds quite bad, but that's the best
case scenario where gpio interrupt is handled right away without any
delay (so more than TxFIFO characters can actually be transmitted).

Does the internal RTS default to inactive when it's not pinmuxed to the
actual pin? If so, then controlling UCR2_IRTS based on CTS gpio could
halt the transmission when the TxFIFO is not empty.

Best Regards,
Tomasz Mon
Tim Harvey Feb. 15, 2022, 5:26 p.m. UTC | #2
On Mon, Feb 14, 2022 at 10:03 PM Tomasz Moń <tomasz.mon@camlingroup.com> wrote:
>
> On 14.02.2022 22:30, Tim Harvey wrote:
> > If using modem-control gpios for CTS we must leave IRTS disabled
> > as otherwise the hardware will only transmit based on the internal RTS
> > pin routed to it.
> >
> > This allows hardware flow control to be used with cts-gpios.
>
> This hardware flow control sounds quite limited. Once CTS becomes
> inactive, the transmitter will still output all characters from TxFIFO.
> Transmitting whole TxFIFO already sounds quite bad, but that's the best
> case scenario where gpio interrupt is handled right away without any
> delay (so more than TxFIFO characters can actually be transmitted).
>
> Does the internal RTS default to inactive when it's not pinmuxed to the
> actual pin? If so, then controlling UCR2_IRTS based on CTS gpio could
> halt the transmission when the TxFIFO is not empty.
>

Tomasz,

I agree that the increased latency makes using a GPIO for CTS
(software controlled) not as good as one pinmuxed into the UART block
directly (hardware controlled) but without this patch GPIO for CTS
does not work at all because the internal RTS defaults to inactive
when its not pinmuxed. For many applications the latency is not an
issue.

Best Regards,

Tim
Tomasz Moń Feb. 16, 2022, 5:45 a.m. UTC | #3
On 15.02.2022 18:26, Tim Harvey wrote:
> On Mon, Feb 14, 2022 at 10:03 PM Tomasz Moń <tomasz.mon@camlingroup.com> wrote:
>> This hardware flow control sounds quite limited. Once CTS becomes
>> inactive, the transmitter will still output all characters from TxFIFO.
>> Transmitting whole TxFIFO already sounds quite bad, but that's the best
>> case scenario where gpio interrupt is handled right away without any
>> delay (so more than TxFIFO characters can actually be transmitted).
>>
>> Does the internal RTS default to inactive when it's not pinmuxed to the
>> actual pin? If so, then controlling UCR2_IRTS based on CTS gpio could
>> halt the transmission when the TxFIFO is not empty.
>>> I agree that the increased latency makes using a GPIO for CTS
> (software controlled) not as good as one pinmuxed into the UART block
> directly (hardware controlled) but without this patch GPIO for CTS
> does not work at all because the internal RTS defaults to inactive
> when its not pinmuxed. For many applications the latency is not an
> issue.

I think I didn't write the message clear enough. I agree, that the GPIO
handling time is something the user has to accept. Usually this part
alone is not that bad though, as many receivers are capable of receiving
more than one character after deasserting their RTS output (transmitter
CTS input).

The general expectation is that the transmitter will output maximum one
more character *after* CTS GPIO change is handled by software. This is
not the case with current version of the patch.

With current version of the patch, after CTS GPIO handler finishes, the
UART will continue to transmit up to 32 characters if not using DMA.
When DMA is active it is much worse, as it will keep transmitting all
data already submitted to dmaengine.

As the internal RTS defaults to inactive when its not pinmuxed, the
software is able to freeze the TxFIFO (and thus DMA if enabled). To
freeze TxFIFO when using CTS GPIO, the software has to clear IRTS bit in
UCR2 register. Setting IRTS will thaw the TxFIFO.

Best Regards,
Tomasz Mon
Tim Harvey Feb. 17, 2022, 4:22 p.m. UTC | #4
On Tue, Feb 15, 2022 at 9:45 PM Tomasz Moń <tomasz.mon@camlingroup.com> wrote:
>
> On 15.02.2022 18:26, Tim Harvey wrote:
> > On Mon, Feb 14, 2022 at 10:03 PM Tomasz Moń <tomasz.mon@camlingroup.com> wrote:
> >> This hardware flow control sounds quite limited. Once CTS becomes
> >> inactive, the transmitter will still output all characters from TxFIFO.
> >> Transmitting whole TxFIFO already sounds quite bad, but that's the best
> >> case scenario where gpio interrupt is handled right away without any
> >> delay (so more than TxFIFO characters can actually be transmitted).
> >>
> >> Does the internal RTS default to inactive when it's not pinmuxed to the
> >> actual pin? If so, then controlling UCR2_IRTS based on CTS gpio could
> >> halt the transmission when the TxFIFO is not empty.
> >>> I agree that the increased latency makes using a GPIO for CTS
> > (software controlled) not as good as one pinmuxed into the UART block
> > directly (hardware controlled) but without this patch GPIO for CTS
> > does not work at all because the internal RTS defaults to inactive
> > when its not pinmuxed. For many applications the latency is not an
> > issue.
>
> I think I didn't write the message clear enough. I agree, that the GPIO
> handling time is something the user has to accept. Usually this part
> alone is not that bad though, as many receivers are capable of receiving
> more than one character after deasserting their RTS output (transmitter
> CTS input).
>
> The general expectation is that the transmitter will output maximum one
> more character *after* CTS GPIO change is handled by software. This is
> not the case with current version of the patch.
>
> With current version of the patch, after CTS GPIO handler finishes, the
> UART will continue to transmit up to 32 characters if not using DMA.
> When DMA is active it is much worse, as it will keep transmitting all
> data already submitted to dmaengine.
>
> As the internal RTS defaults to inactive when its not pinmuxed, the
> software is able to freeze the TxFIFO (and thus DMA if enabled). To
> freeze TxFIFO when using CTS GPIO, the software has to clear IRTS bit in
> UCR2 register. Setting IRTS will thaw the TxFIFO.
>

Tomasz,

Ok - I understand what you are saying. Yes, I should be able to use
IRTS to freeze/thaw the transmitter based on it being inactive when
not pinmuxed. I will work on a v2.

Thanks for the explanation!

Best Regards,

Tim
diff mbox series

Patch

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index df8a0c8b8b29..bf2bb987a51f 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -201,6 +201,7 @@  struct imx_port {
 	unsigned int		old_status;
 	unsigned int		have_rtscts:1;
 	unsigned int		have_rtsgpio:1;
+	unsigned int		have_ctsgpio:1;
 	unsigned int		dte_mode:1;
 	unsigned int		inverted_tx:1;
 	unsigned int		inverted_rx:1;
@@ -1674,8 +1675,7 @@  imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 		if (ucr2 & UCR2_CTS)
 			ucr2 |= UCR2_CTSC;
 	}
-
-	if (termios->c_cflag & CRTSCTS)
+	if (!sport->have_ctsgpio && termios->c_cflag & CRTSCTS)
 		ucr2 &= ~UCR2_IRTS;
 	if (termios->c_cflag & CSTOPB)
 		ucr2 |= UCR2_STPB;
@@ -2227,6 +2227,9 @@  static int imx_uart_probe(struct platform_device *pdev)
 	if (of_get_property(np, "fsl,dte-mode", NULL))
 		sport->dte_mode = 1;
 
+	if (of_get_property(np, "cts-gpios", NULL))
+		sport->have_ctsgpio = 1;
+
 	if (of_get_property(np, "rts-gpios", NULL))
 		sport->have_rtsgpio = 1;