diff options
Diffstat (limited to 'drivers/tty/serial/omap-serial.c')
| -rw-r--r-- | drivers/tty/serial/omap-serial.c | 51 | 
1 files changed, 28 insertions, 23 deletions
| diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 76b94d0ff586..84e8158088cd 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -159,6 +159,8 @@ struct uart_omap_port {  	u32			calc_latency;  	struct work_struct	qos_work;  	bool			is_suspending; + +	unsigned int		rs485_tx_filter_count;  };  #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) @@ -302,7 +304,8 @@ static void serial_omap_stop_tx(struct uart_port *port)  			serial_out(up, UART_OMAP_SCR, up->scr);  			res = (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ?  				1 : 0; -			if (gpiod_get_value(up->rts_gpiod) != res) { +			if (up->rts_gpiod && +			    gpiod_get_value(up->rts_gpiod) != res) {  				if (port->rs485.delay_rts_after_send > 0)  					mdelay(  					port->rs485.delay_rts_after_send); @@ -328,19 +331,6 @@ static void serial_omap_stop_tx(struct uart_port *port)  		serial_out(up, UART_IER, up->ier);  	} -	if ((port->rs485.flags & SER_RS485_ENABLED) && -	    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) { -		/* -		 * Empty the RX FIFO, we are not interested in anything -		 * received during the half-duplex transmission. -		 */ -		serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_RCVR); -		/* Re-enable RX interrupts */ -		up->ier |= UART_IER_RLSI | UART_IER_RDI; -		up->port.read_status_mask |= UART_LSR_DR; -		serial_out(up, UART_IER, up->ier); -	} -  	pm_runtime_mark_last_busy(up->dev);  	pm_runtime_put_autosuspend(up->dev);  } @@ -366,6 +356,10 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)  		serial_out(up, UART_TX, up->port.x_char);  		up->port.icount.tx++;  		up->port.x_char = 0; +		if ((up->port.rs485.flags & SER_RS485_ENABLED) && +		    !(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) +			up->rs485_tx_filter_count++; +  		return;  	}  	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { @@ -377,6 +371,10 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)  		serial_out(up, UART_TX, xmit->buf[xmit->tail]);  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);  		up->port.icount.tx++; +		if ((up->port.rs485.flags & SER_RS485_ENABLED) && +		    !(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) +			up->rs485_tx_filter_count++; +  		if (uart_circ_empty(xmit))  			break;  	} while (--count > 0); @@ -411,7 +409,7 @@ static void serial_omap_start_tx(struct uart_port *port)  		/* if rts not already enabled */  		res = (port->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0; -		if (gpiod_get_value(up->rts_gpiod) != res) { +		if (up->rts_gpiod && gpiod_get_value(up->rts_gpiod) != res) {  			gpiod_set_value(up->rts_gpiod, res);  			if (port->rs485.delay_rts_before_send > 0)  				mdelay(port->rs485.delay_rts_before_send); @@ -420,7 +418,7 @@ static void serial_omap_start_tx(struct uart_port *port)  	if ((port->rs485.flags & SER_RS485_ENABLED) &&  	    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) -		serial_omap_stop_rx(port); +		up->rs485_tx_filter_count = 0;  	serial_omap_enable_ier_thri(up);  	pm_runtime_mark_last_busy(up->dev); @@ -491,8 +489,13 @@ static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr)  	 * Read one data character out to avoid stalling the receiver according  	 * to the table 23-246 of the omap4 TRM.  	 */ -	if (likely(lsr & UART_LSR_DR)) +	if (likely(lsr & UART_LSR_DR)) {  		serial_in(up, UART_RX); +		if ((up->port.rs485.flags & SER_RS485_ENABLED) && +		    !(up->port.rs485.flags & SER_RS485_RX_DURING_TX) && +		    up->rs485_tx_filter_count) +			up->rs485_tx_filter_count--; +	}  	up->port.icount.rx++;  	flag = TTY_NORMAL; @@ -543,6 +546,13 @@ static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)  		return;  	ch = serial_in(up, UART_RX); +	if ((up->port.rs485.flags & SER_RS485_ENABLED) && +	    !(up->port.rs485.flags & SER_RS485_RX_DURING_TX) && +	    up->rs485_tx_filter_count) { +		up->rs485_tx_filter_count--; +		return; +	} +  	flag = TTY_NORMAL;  	up->port.icount.rx++; @@ -1407,18 +1417,13 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)  	/* store new config */  	port->rs485 = *rs485; -	/* -	 * Just as a precaution, only allow rs485 -	 * to be enabled if the gpio pin is valid -	 */  	if (up->rts_gpiod) {  		/* enable / disable rts */  		val = (port->rs485.flags & SER_RS485_ENABLED) ?  			SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;  		val = (port->rs485.flags & val) ? 1 : 0;  		gpiod_set_value(up->rts_gpiod, val); -	} else -		port->rs485.flags &= ~SER_RS485_ENABLED; +	}  	/* Enable interrupts */  	up->ier = mode; | 
