Re: [RFC] serial: imx: Fix the polarity of RTS GPIO pin

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

 



On Wed, Jan 25, 2017 at 04:11:38PM -0200, Fabio Estevam wrote:
> Hi Uwe,
> 
> On Wed, Jan 25, 2017 at 4:59 AM, Uwe Kleine-König
> <u.kleine-koenig@xxxxxxxxxxxxxx> wrote:
> 
> > Right, that looks fishy. It was introduced in 58362d5be3521 which keeps
> > the behaviour of the hw rts. I.e. if SER_RS485_RTS_AFTER_SEND is set it
> > clears UCR2_CTS. This means "The CTS pin is high (inactive)". This is
> > wrong, too, isn't it? So the wrong commit is 17b8f2a3fdca and
> > 58362d5be3521 only consistently expanded it.
> 
> What about this?
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 33fcc84..e3e152c 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -336,15 +336,15 @@ static void imx_port_ucrs_restore(struct uart_port *port,
>  
>  static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2)
>  {
> -	*ucr2 &= ~UCR2_CTSC;
> -	*ucr2 |= UCR2_CTS;
> +	*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
>  
>  	mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS);
>  }
>  
>  static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2)
>  {
> -	*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
> +	*ucr2 &= ~UCR2_CTSC;
> +	*ucr2 |= UCR2_CTS;
>  
>  	mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS);
>  }

I think the above is wrong. Setting CTS makes the CTS pin low (active).
So AFAICT (that is without testing) drop this hunk.

> @@ -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);

This and the rest looks ok. If SER_RS485_RTS_AFTER_SEND make it active
in imx_stop_tx.
>  
> @@ -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);
>  	}
> 
> With this patch I can get rs485 in half-duplex mode to work correctly with
> rts-gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>;
> 
> I do not have a board that uses the native CTS pin connected to the
> TXEN pin of a RS485 transceiver, but I have enabled another UART that
> exposes CTS pin and I can see it going to 1 during transmission and 0
> after that.

Please compare the level of the CTS pin you see with the rts-gpio. Do
they match (logically) given that RTS is active low?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
--
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