diff options
Diffstat (limited to 'drivers/tty/serial/bfin_uart.c')
| -rw-r--r-- | drivers/tty/serial/bfin_uart.c | 83 | 
1 files changed, 37 insertions, 46 deletions
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 66afb98b77b..26953bfa692 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -116,15 +116,22 @@ static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)  static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id)  {  	struct bfin_serial_port *uart = dev_id; -	unsigned int status; - -	status = bfin_serial_get_mctrl(&uart->port); -	uart_handle_cts_change(&uart->port, status & TIOCM_CTS); +	unsigned int status = bfin_serial_get_mctrl(&uart->port);  #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS -	uart->scts = 1; +	struct tty_struct *tty = uart->port.state->port.tty; +  	UART_CLEAR_SCTS(uart); -	UART_CLEAR_IER(uart, EDSSI); +	if (tty->hw_stopped) { +		if (status) { +			tty->hw_stopped = 0; +			uart_write_wakeup(&uart->port); +		} +	} else { +		if (!status) +			tty->hw_stopped = 1; +	}  #endif +	uart_handle_cts_change(&uart->port, status & TIOCM_CTS);  	return IRQ_HANDLED;  } @@ -175,13 +182,6 @@ static void bfin_serial_start_tx(struct uart_port *port)  	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;  	struct tty_struct *tty = uart->port.state->port.tty; -#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS -	if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) { -		uart->scts = 0; -		uart_handle_cts_change(&uart->port, uart->scts); -	} -#endif -  	/*  	 * To avoid losting RX interrupt, we reset IR function  	 * before sending data. @@ -380,12 +380,6 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)  {  	struct bfin_serial_port *uart = dev_id; -#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS -	if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) { -		uart->scts = 0; -		uart_handle_cts_change(&uart->port, uart->scts); -	} -#endif  	spin_lock(&uart->port.lock);  	if (UART_GET_LSR(uart) & THRE)  		bfin_serial_tx_chars(uart); @@ -531,13 +525,6 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)  	struct bfin_serial_port *uart = dev_id;  	struct circ_buf *xmit = &uart->port.state->xmit; -#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS -	if (uart->scts && !(bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) { -		uart->scts = 0; -		uart_handle_cts_change(&uart->port, uart->scts); -	} -#endif -  	spin_lock(&uart->port.lock);  	if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {  		disable_dma(uart->tx_dma_channel); @@ -739,20 +726,26 @@ static int bfin_serial_startup(struct uart_port *port)  			pr_info("Unable to attach BlackFin UART CTS interrupt. So, disable it.\n");  		}  	} -	if (uart->rts_pin >= 0) -		gpio_direction_output(uart->rts_pin, 0); +	if (uart->rts_pin >= 0) { +		if (gpio_request(uart->rts_pin, DRIVER_NAME)) { +			pr_info("fail to request RTS PIN at GPIO_%d\n", uart->rts_pin); +			uart->rts_pin = -1; +		} else +			gpio_direction_output(uart->rts_pin, 0); +	}  #endif  #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS -	if (uart->cts_pin >= 0 && request_irq(uart->status_irq, -		bfin_serial_mctrl_cts_int, -		0, "BFIN_UART_MODEM_STATUS", uart)) { -		uart->cts_pin = -1; -		pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n"); -	} +	if (uart->cts_pin >= 0) { +		if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int, +			IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) { +			uart->cts_pin = -1; +			dev_info(port->dev, "Unable to attach BlackFin UART Modem Status interrupt.\n"); +		} -	/* CTS RTS PINs are negative assertive. */ -	UART_PUT_MCR(uart, ACTS); -	UART_SET_IER(uart, EDSSI); +		/* CTS RTS PINs are negative assertive. */ +		UART_PUT_MCR(uart, ACTS); +		UART_SET_IER(uart, EDSSI); +	}  #endif  	UART_SET_IER(uart, ERBFI); @@ -792,6 +785,8 @@ static void bfin_serial_shutdown(struct uart_port *port)  #ifdef CONFIG_SERIAL_BFIN_CTSRTS  	if (uart->cts_pin >= 0)  		free_irq(gpio_to_irq(uart->cts_pin), uart); +	if (uart->rts_pin >= 0) +		gpio_free(uart->rts_pin);  #endif  #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS  	if (uart->cts_pin >= 0) @@ -1370,18 +1365,18 @@ static int bfin_serial_probe(struct platform_device *pdev)  		res = platform_get_resource(pdev, IORESOURCE_IO, 0);  		if (res == NULL)  			uart->cts_pin = -1; -		else +		else {  			uart->cts_pin = res->start; +#ifdef CONFIG_SERIAL_BFIN_CTSRTS +			uart->port.flags |= ASYNC_CTS_FLOW; +#endif +		}  		res = platform_get_resource(pdev, IORESOURCE_IO, 1);  		if (res == NULL)  			uart->rts_pin = -1;  		else  			uart->rts_pin = res->start; -# if defined(CONFIG_SERIAL_BFIN_CTSRTS) -		if (uart->rts_pin >= 0) -			gpio_request(uart->rts_pin, DRIVER_NAME); -# endif  #endif  	} @@ -1421,10 +1416,6 @@ static int __devexit bfin_serial_remove(struct platform_device *pdev)  	if (uart) {  		uart_remove_one_port(&bfin_serial_reg, &uart->port); -#ifdef CONFIG_SERIAL_BFIN_CTSRTS -		if (uart->rts_pin >= 0) -			gpio_free(uart->rts_pin); -#endif  		iounmap(uart->port.membase);  		peripheral_free_list(  			(unsigned short *)pdev->dev.platform_data);  |