Re: [PATCH 1/2] serial: imx: Fix the RTS GPIO polarity in RS485 mode

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

 



On Mon, Jan 30, 2017 at 3:12 AM, Fabio Estevam <festevam@xxxxxxxxx> wrote:
> From: Fabio Estevam <fabio.estevam@xxxxxxx>
>
> On a board that needs to drive RTS GPIO high in order to enable the
> transmission of a RS485 transceiver the following description is
> passed in the devide tree:
>
> &uart4 {
>         pinctrl-names = "default";
>         pinctrl-0 = <&pinctrl_uart4>;
>         rts-gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>;
>         status = "okay";
> };
>
> and userspace configures the uart port as follows:
>
> /* enable RS485 mode: */
> rs485conf.flags |= SER_RS485_ENABLED;
>
> /* set logical level for RTS pin equal to 1 when sending: */
> rs485conf.flags |= SER_RS485_RTS_ON_SEND;
>
> /* set logical level for RTS pin equal to 0 after sending: */
> rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
>
> However the RTS GPIO polarity observed in the oscilloscope is inverted.
>
> When the SER_RS485_RTS_ON_SEND flag is set the imx_port_rts_active()
> function should be called and following the same logic when
> SER_RS485_RTS_AFTER_SEND flag is cleared the imx_port_rts_inactive()
> should be called.
>
> Do such logic change so that RS485 communication in half duplex can
> work successfully when the RTS GPIO pin is passed via device tree.
>
> Signed-off-by: Fabio Estevam <fabio.estevam@xxxxxxx>
> ---
>  drivers/tty/serial/imx.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 33fcc84..29dd57c 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -377,9 +377,9 @@ static void imx_stop_tx(struct uart_port *port)
>             readl(port->membase + USR2) & USR2_TXDC) {
>                 temp = readl(port->membase + UCR2);
>                 if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
> -                       imx_port_rts_inactive(sport, &temp);
> -               else
>                         imx_port_rts_active(sport, &temp);
> +               else
> +                       imx_port_rts_inactive(sport, &temp);
>                 temp |= UCR2_RXEN;
>                 writel(temp, port->membase + UCR2);
>
> @@ -585,9 +585,9 @@ static void imx_start_tx(struct uart_port *port)
>         if (port->rs485.flags & SER_RS485_ENABLED) {
>                 temp = readl(port->membase + UCR2);
>                 if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
> -                       imx_port_rts_inactive(sport, &temp);
> -               else
>                         imx_port_rts_active(sport, &temp);
> +               else
> +                       imx_port_rts_inactive(sport, &temp);
>                 if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
>                         temp &= ~UCR2_RXEN;
>                 writel(temp, port->membase + UCR2);
> @@ -1477,9 +1477,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
>                                  */
>                                 if (port->rs485.flags &
>                                     SER_RS485_RTS_AFTER_SEND)
> -                                       imx_port_rts_inactive(sport, &ucr2);
> -                               else
>                                         imx_port_rts_active(sport, &ucr2);
> +                               else
> +                                       imx_port_rts_inactive(sport, &ucr2);
>                         } else {
>                                 imx_port_rts_auto(sport, &ucr2);
>                         }
> @@ -1489,9 +1489,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
>         } else if (port->rs485.flags & SER_RS485_ENABLED) {
>                 /* disable transmitter */
>                 if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
> -                       imx_port_rts_inactive(sport, &ucr2);
> -               else
>                         imx_port_rts_active(sport, &ucr2);
> +               else
> +                       imx_port_rts_inactive(sport, &ucr2);
>         }
>
>
> @@ -1733,9 +1733,9 @@ static int imx_rs485_config(struct uart_port *port,
>                 /* disable transmitter */
>                 temp = readl(sport->port.membase + UCR2);
>                 if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
> -                       imx_port_rts_inactive(sport, &temp);
> -               else
>                         imx_port_rts_active(sport, &temp);
> +               else
> +                       imx_port_rts_inactive(sport, &temp);
>                 writel(temp, sport->port.membase + UCR2);
>         }
>
> --
> 2.7.4
>

Fabio,

Works great for me with respect to TXEN polarity thanks!

Something I noticed this time around while testing however is that in
some cases I'm not getting the dma_tx_callback telling us the tx dma
completed causing the stop_tx to return and the TXEN to not be
de-asserted. I hadn't noticed this before. Have you encountered it in
your use/testing?

Regards,

Tim
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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