tty: serial: lpuart: Fix the logic for detecting the 32-bit type UART
Commit0d6fce9044
("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:0d6fce9044
("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>
This commit is contained in:
parent
514ab34dba
commit
3ee5447e8c
|
@ -619,6 +619,12 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
|
||||||
TIOCSER_TEMT : 0;
|
TIOCSER_TEMT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool lpuart_is_32(struct lpuart_port *sport)
|
||||||
|
{
|
||||||
|
return sport->port.iotype == UPIO_MEM32 ||
|
||||||
|
sport->port.iotype == UPIO_MEM32BE;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct lpuart_port *sport = dev_id;
|
struct lpuart_port *sport = dev_id;
|
||||||
|
@ -627,7 +633,7 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
||||||
|
|
||||||
spin_lock_irqsave(&sport->port.lock, flags);
|
spin_lock_irqsave(&sport->port.lock, flags);
|
||||||
if (sport->port.x_char) {
|
if (sport->port.x_char) {
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
|
if (lpuart_is_32(sport))
|
||||||
lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
|
lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
|
||||||
else
|
else
|
||||||
writeb(sport->port.x_char, sport->port.membase + UARTDR);
|
writeb(sport->port.x_char, sport->port.membase + UARTDR);
|
||||||
|
@ -635,14 +641,14 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
|
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
|
if (lpuart_is_32(sport))
|
||||||
lpuart32_stop_tx(&sport->port);
|
lpuart32_stop_tx(&sport->port);
|
||||||
else
|
else
|
||||||
lpuart_stop_tx(&sport->port);
|
lpuart_stop_tx(&sport->port);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
|
if (lpuart_is_32(sport))
|
||||||
lpuart32_transmit_buffer(sport);
|
lpuart32_transmit_buffer(sport);
|
||||||
else
|
else
|
||||||
lpuart_transmit_buffer(sport);
|
lpuart_transmit_buffer(sport);
|
||||||
|
@ -1978,12 +1984,12 @@ static int __init lpuart_console_setup(struct console *co, char *options)
|
||||||
if (options)
|
if (options)
|
||||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||||
else
|
else
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
|
if (lpuart_is_32(sport))
|
||||||
lpuart32_console_get_options(sport, &baud, &parity, &bits);
|
lpuart32_console_get_options(sport, &baud, &parity, &bits);
|
||||||
else
|
else
|
||||||
lpuart_console_get_options(sport, &baud, &parity, &bits);
|
lpuart_console_get_options(sport, &baud, &parity, &bits);
|
||||||
|
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
|
if (lpuart_is_32(sport))
|
||||||
lpuart32_setup_watermark(sport);
|
lpuart32_setup_watermark(sport);
|
||||||
else
|
else
|
||||||
lpuart_setup_watermark(sport);
|
lpuart_setup_watermark(sport);
|
||||||
|
@ -2118,7 +2124,7 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
sport->port.irq = ret;
|
sport->port.irq = ret;
|
||||||
sport->port.iotype = sdata->iotype;
|
sport->port.iotype = sdata->iotype;
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
|
if (lpuart_is_32(sport))
|
||||||
sport->port.ops = &lpuart32_pops;
|
sport->port.ops = &lpuart32_pops;
|
||||||
else
|
else
|
||||||
sport->port.ops = &lpuart_pops;
|
sport->port.ops = &lpuart_pops;
|
||||||
|
@ -2145,7 +2151,7 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, &sport->port);
|
platform_set_drvdata(pdev, &sport->port);
|
||||||
|
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
|
if (lpuart_is_32(sport))
|
||||||
lpuart_reg.cons = LPUART32_CONSOLE;
|
lpuart_reg.cons = LPUART32_CONSOLE;
|
||||||
else
|
else
|
||||||
lpuart_reg.cons = LPUART_CONSOLE;
|
lpuart_reg.cons = LPUART_CONSOLE;
|
||||||
|
@ -2198,7 +2204,7 @@ static int lpuart_suspend(struct device *dev)
|
||||||
struct lpuart_port *sport = dev_get_drvdata(dev);
|
struct lpuart_port *sport = dev_get_drvdata(dev);
|
||||||
unsigned long temp;
|
unsigned long temp;
|
||||||
|
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) {
|
if (lpuart_is_32(sport)) {
|
||||||
/* disable Rx/Tx and interrupts */
|
/* disable Rx/Tx and interrupts */
|
||||||
temp = lpuart32_read(&sport->port, UARTCTRL);
|
temp = lpuart32_read(&sport->port, UARTCTRL);
|
||||||
temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE);
|
temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE);
|
||||||
|
@ -2249,7 +2255,7 @@ static int lpuart_resume(struct device *dev)
|
||||||
if (sport->port.suspended && !sport->port.irq_wake)
|
if (sport->port.suspended && !sport->port.irq_wake)
|
||||||
clk_prepare_enable(sport->clk);
|
clk_prepare_enable(sport->clk);
|
||||||
|
|
||||||
if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) {
|
if (lpuart_is_32(sport)) {
|
||||||
lpuart32_setup_watermark(sport);
|
lpuart32_setup_watermark(sport);
|
||||||
temp = lpuart32_read(&sport->port, UARTCTRL);
|
temp = lpuart32_read(&sport->port, UARTCTRL);
|
||||||
temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE |
|
temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE |
|
||||||
|
|
Loading…
Reference in New Issue