Re: Modem control lines for RTSCTS hardware flow control via rts-gpio and cts-gpio with IMX

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jan 24, 2022 at 1:52 AM Richard Genoud <richard.genoud@xxxxxxxxx> wrote:
>
>
> Hi,
>
> Le 14/01/2022 à 07:19, Tomasz Moń a écrit :
> > On 14.01.2022 04:08, Tim Harvey wrote:
> >> So I believe in order to support using gpios for rts/cts in the imx
> >> uart driver I must find the right place to call imx_uart_rts_active
> >> and imx_uart_rts_inactive when the FIFO is not full and full
> >> respectively. I'm not that familiar with the Linux uart driver
> >> framework - am I on the right track and if so any ideas where this is
> >> best done?
> >
> > It is not really the driver (and thus FIFO level), but rather the amount
> > of free space in tty buffer (checked by Line Discipline workqueue) that
> > determines when to throttle (set RTS inactive). This mostly works fine,
> > but fails [1] when the RX interrupt frequency is too high [2].
> >
> > The throttle/unthrottle request, when termios CRTSCTS is set, is seen by
> > the driver as the call to .set_mctrl (imx_uart_set_mctrl) with TIOCM_RTS
> > bit cleared/set in mctrl parameter. Currently imx_uart_set_mctrl() only
> > controls the UCR2_CTS and UCR2_CTSC bits based on mctrl.
> >
> > To support your case you would most likely have to add the gpio handling
> > in imx_uart_set_mctrl(). However, I am unaware what other issues you
> > might encounter (i.e. if it is not done there yet simply because nobody
> > had that use case or if there is some deeper problem).
> >
> > [1] https://lore.kernel.org/linux-serial/10e723c0-a28b-de0d-0632-0bd250478313@xxxxxxxxxxxxxxx/
> > [2] https://lore.kernel.org/linux-serial/20220104103203.2033673-1-tomasz.mon@xxxxxxxxxxxxxxx/
> >
> > Best Regards,
> > Tomasz Mon
> >
>
> I'd suggest to start testing with a serial port connected to nothing, and check the pins values
> with a scope or a voltmeter.
> Setting pins values from userspace can done quite easily with :
> #include <unistd.h>
> #include <termios.h>
> #include <stdio.h>
> #include <sys/ioctl.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
>
> void usage(char *prog)
> {
>         printf("usage: %s serial_port id 0/1 sleep_time_sec\n", prog);
>         printf("%s\n", "1:DTR   DTR (data terminal ready)");
>         printf("%s\n", "2:RTS   RTS (request to send)");
>         printf("%s\n", "3:Both");
> }
>
> int main(int argc, char **argv)
> {
>         int fd;
>         unsigned status = 0;
>         int enable;
>         int err;
>
>         if (argc < 5) {
>                 usage(argv[0]);
>                 return -1;
>         }
>
>         fd = open(argv[1], O_RDWR | O_NOCTTY);
>
>         enable = atoi(argv[3]);
>
>         if (fd < 0)
>                 return -1;
>
>
>         switch(atoi(argv[2])) {
>         case 0:
>                 if (enable)
>                         status |= TIOCM_LE;
>                 break;
>         case 1:
>                 if (enable)
>                         status |= TIOCM_DTR;
>                 break;
>         case 2:
>                 if (enable)
>                         status |= TIOCM_RTS;
>                 break;
>         case 3:
>                 if (enable)
>                         status |= TIOCM_DTR | TIOCM_RTS;
>                 break;
>         default:
>                 printf("unknown signal\n");
>         }
>
>         err = ioctl(fd, TIOCMSET, &status);
>         sleep(atoi(argv[4]));
> out:
>         if (fd > -1)
>                 close(fd);
>
>         return err;
> }
>

Richard,

Thanks, I've been able to use this as well as terminal apps like
picocom and a scope to ensure that the RTS gpio is getting asserted
properly and that the CTS gpio is getting handled accordingly. Both
these signals are configured with internal pull-ups.

With for example:
        cts-gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; // input to IMX
        rts-gpios = <&gpio6 3 GPIO_ACTIVE_LOW>; // output from IMX

I see that when rts is set to 1 (ie 'uart_test /dev/ttymxc3 2 1 3' or
'picocom /dev/ttymxc3 --flow h') the normally pulled-up logic high RTS
gpio goes to 0V and when rts is set to 0 it goes back to 3.3V via the
pull-up.

I've also been able to add debugging to ensure that when the CTS
signal is manually grounded that mctrl_gpio_irq_handle is called with
CTS=1 and imx_uart_start_tx is called to enable transmission and when
CTS signal is released from GND going back to 3.3V via the pull-up
mctrl_gpio_irq_handle is called with CTS=0 and imx_uart_stop_tx is
called to halt transmission.

I've also verified that changing the gpio descriptor in the dts above
to GPIO_ACTIVE_HIGH negates the above logic which is clearly wrong as
these are active-low signals.

In this specific case the device I am connecting the IMX
UART3_TX/UART3_RX and the GPIO's for RTS/CTS to is a Laird
Sterling-LWB wifi/BT chip. The datasheet [1] shows:
pin 31: BT_UART_RTS_L output UART Request-to-send
pin 32: BT_UART_CTS_L input UART Clear-to-send
pin 33: BT_UART_TXD output UART transmit
pin 34: BT_UART_RXD input UART input

They are connected to the IMX as:
BT_UART_RXD(pin34) <- IMX CSI0_DAT12_UART4_TXD
BT_UART_TXD(pin33) -> IMX CSI0_DAT13_UART4_RXD
BT_UART_CTS_L(pin32) <- IMX CSI0_DAT17_UART4_RTS_B (GPIO6_IO3)
BT_UART_RTS_L(pin31) -> IMX CSI0_DAT16_UART4_CTS_B (GPIO6_IO2)

And again if pinmuxed as RTS/CTS communication with the BT HCI is fine
but if pinmuxed as GPIO and configured as the following BT HCI
communication fails:
        cts-gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* in to IMX from HCI
BT_UART_RTS_L output */
        rts-gpios = <&gpio6 3 GPIO_ACTIVE_LOW>; /* out from IMX to HCI
BT_UART_CTS_L input */

I'm not sure what else to look at here.

Best regards,

Tim
[1] - https://www.lairdconnect.com/documentation/datasheet-sterling-lwb




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux