aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@nxp.com>2017-07-11 07:03:43 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-07-17 08:14:24 -0400
commit3ee5447e8cd9a65d08fbb49fa9767cbf7fef6d91 (patch)
treebb96b6c9eec940fd0ecc86e14fc92f6b6a099943
parent514ab34dbad6c6fa824a1f56984c196e59082346 (diff)
tty: serial: lpuart: Fix the logic for detecting the 32-bit type UART
Commit 0d6fce904452 ("tty: serial: lpuart: introduce lpuart_soc_data to represent SoC property") introduced a buggy logic for detecting the 32-bit type UART since the condition: "if (sport->port.iotype & UPIO_MEM32BE)" is always true. Performing such bitfield AND operation is not correct, because in the case of Vybrid UART iotype is UPIO_MEM (2), so: UPIO_MEM & UPIO_MEM32BE = 010 & 110 = 010, which is true. Such logic tells the driver to always treat the UART operations as 32-bit, leading to the driver misbehavior on Vybrid. Fix the 32-bit type detection logic to avoid UART breakage on Vybrid. While at it, introduce a lpuart_is_32() function to help readability. Fixes: 0d6fce904452 ("tty: serial: lpuart: introduce lpuart_soc_data to represent SoC property") Reported-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com> Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com> Tested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/fsl_lpuart.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 343de8c384b0..898dcb091a27 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -619,6 +619,12 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
619 TIOCSER_TEMT : 0; 619 TIOCSER_TEMT : 0;
620} 620}
621 621
622static bool lpuart_is_32(struct lpuart_port *sport)
623{
624 return sport->port.iotype == UPIO_MEM32 ||
625 sport->port.iotype == UPIO_MEM32BE;
626}
627
622static irqreturn_t lpuart_txint(int irq, void *dev_id) 628static irqreturn_t lpuart_txint(int irq, void *dev_id)
623{ 629{
624 struct lpuart_port *sport = dev_id; 630 struct lpuart_port *sport = dev_id;
@@ -627,7 +633,7 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
627 633
628 spin_lock_irqsave(&sport->port.lock, flags); 634 spin_lock_irqsave(&sport->port.lock, flags);
629 if (sport->port.x_char) { 635 if (sport->port.x_char) {
630 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) 636 if (lpuart_is_32(sport))
631 lpuart32_write(&sport->port, sport->port.x_char, UARTDATA); 637 lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
632 else 638 else
633 writeb(sport->port.x_char, sport->port.membase + UARTDR); 639 writeb(sport->port.x_char, sport->port.membase + UARTDR);
@@ -635,14 +641,14 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
635 } 641 }
636 642
637 if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { 643 if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
638 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) 644 if (lpuart_is_32(sport))
639 lpuart32_stop_tx(&sport->port); 645 lpuart32_stop_tx(&sport->port);
640 else 646 else
641 lpuart_stop_tx(&sport->port); 647 lpuart_stop_tx(&sport->port);
642 goto out; 648 goto out;
643 } 649 }
644 650
645 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) 651 if (lpuart_is_32(sport))
646 lpuart32_transmit_buffer(sport); 652 lpuart32_transmit_buffer(sport);
647 else 653 else
648 lpuart_transmit_buffer(sport); 654 lpuart_transmit_buffer(sport);
@@ -1978,12 +1984,12 @@ static int __init lpuart_console_setup(struct console *co, char *options)
1978 if (options) 1984 if (options)
1979 uart_parse_options(options, &baud, &parity, &bits, &flow); 1985 uart_parse_options(options, &baud, &parity, &bits, &flow);
1980 else 1986 else
1981 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) 1987 if (lpuart_is_32(sport))
1982 lpuart32_console_get_options(sport, &baud, &parity, &bits); 1988 lpuart32_console_get_options(sport, &baud, &parity, &bits);
1983 else 1989 else
1984 lpuart_console_get_options(sport, &baud, &parity, &bits); 1990 lpuart_console_get_options(sport, &baud, &parity, &bits);
1985 1991
1986 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) 1992 if (lpuart_is_32(sport))
1987 lpuart32_setup_watermark(sport); 1993 lpuart32_setup_watermark(sport);
1988 else 1994 else
1989 lpuart_setup_watermark(sport); 1995 lpuart_setup_watermark(sport);
@@ -2118,7 +2124,7 @@ static int lpuart_probe(struct platform_device *pdev)
2118 } 2124 }
2119 sport->port.irq = ret; 2125 sport->port.irq = ret;
2120 sport->port.iotype = sdata->iotype; 2126 sport->port.iotype = sdata->iotype;
2121 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) 2127 if (lpuart_is_32(sport))
2122 sport->port.ops = &lpuart32_pops; 2128 sport->port.ops = &lpuart32_pops;
2123 else 2129 else
2124 sport->port.ops = &lpuart_pops; 2130 sport->port.ops = &lpuart_pops;
@@ -2145,7 +2151,7 @@ static int lpuart_probe(struct platform_device *pdev)
2145 2151
2146 platform_set_drvdata(pdev, &sport->port); 2152 platform_set_drvdata(pdev, &sport->port);
2147 2153
2148 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) 2154 if (lpuart_is_32(sport))
2149 lpuart_reg.cons = LPUART32_CONSOLE; 2155 lpuart_reg.cons = LPUART32_CONSOLE;
2150 else 2156 else
2151 lpuart_reg.cons = LPUART_CONSOLE; 2157 lpuart_reg.cons = LPUART_CONSOLE;
@@ -2198,7 +2204,7 @@ static int lpuart_suspend(struct device *dev)
2198 struct lpuart_port *sport = dev_get_drvdata(dev); 2204 struct lpuart_port *sport = dev_get_drvdata(dev);
2199 unsigned long temp; 2205 unsigned long temp;
2200 2206
2201 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) { 2207 if (lpuart_is_32(sport)) {
2202 /* disable Rx/Tx and interrupts */ 2208 /* disable Rx/Tx and interrupts */
2203 temp = lpuart32_read(&sport->port, UARTCTRL); 2209 temp = lpuart32_read(&sport->port, UARTCTRL);
2204 temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE); 2210 temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE);
@@ -2249,7 +2255,7 @@ static int lpuart_resume(struct device *dev)
2249 if (sport->port.suspended && !sport->port.irq_wake) 2255 if (sport->port.suspended && !sport->port.irq_wake)
2250 clk_prepare_enable(sport->clk); 2256 clk_prepare_enable(sport->clk);
2251 2257
2252 if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) { 2258 if (lpuart_is_32(sport)) {
2253 lpuart32_setup_watermark(sport); 2259 lpuart32_setup_watermark(sport);
2254 temp = lpuart32_read(&sport->port, UARTCTRL); 2260 temp = lpuart32_read(&sport->port, UARTCTRL);
2255 temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE | 2261 temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE |