Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: 8250_dw: proper support for UARTs without busy functionality

If the DW_apb_uart is configured with UART_16550_COMPATIBLE
configuration parameter set, then the Busy Functionality is
not available. These UARTs will never generate the Busy
detect indication interrupt, and therefore don't need
handling for it.

This creates a small optimization for the DW_apb_uarts
configured without the busy functionality, but more
importantly, it removes the small but real risk of hitting
potential issues caused by busy functionality handling when
no busy functionality exist.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Heikki Krogerus and committed by
Greg Kroah-Hartman
c73942e2 9e08fa50

+15 -1
+3
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
··· 15 15 Required elements: "baudclk", "apb_pclk" 16 16 17 17 Optional properties: 18 + - snps,uart-16550-compatible : reflects the value of UART_16550_COMPATIBLE 19 + configuration parameter. Define this if your UART does not implement the busy 20 + functionality. 18 21 - resets : phandle to the parent reset controller. 19 22 - reg-shift : quantity to shift the register offsets by. If this property is 20 23 not present then the register offsets are not shifted.
+12 -1
drivers/tty/serial/8250/8250_dw.c
··· 65 65 struct uart_8250_dma dma; 66 66 67 67 unsigned int skip_autocfg:1; 68 + unsigned int uart_16550_compatible:1; 68 69 }; 69 70 70 71 #define BYT_PRV_CLK 0x800 ··· 318 317 p->iotype = UPIO_MEM32; 319 318 p->regshift = 2; 320 319 p->serial_in = dw8250_serial_in32; 321 - p->serial_out = dw8250_serial_out32; 322 320 p->set_termios = dw8250_set_termios; 321 + /* So far none of there implement the Busy Functionality */ 322 + data->uart_16550_compatible = true; 323 323 } 324 324 325 325 /* Platforms with iDMA */ ··· 376 374 377 375 data->usr_reg = DW_UART_USR; 378 376 p->private_data = data; 377 + 378 + data->uart_16550_compatible = device_property_read_bool(p->dev, 379 + "snps,uart-16550-compatible"); 379 380 380 381 err = device_property_read_u32(p->dev, "reg-shift", &val); 381 382 if (!err) ··· 465 460 data->dma.fn = dw8250_dma_filter; 466 461 467 462 dw8250_quirks(p, data); 463 + 464 + /* If the Busy Functionality is not implemented, don't handle it */ 465 + if (data->uart_16550_compatible) { 466 + p->serial_out = NULL; 467 + p->handle_irq = NULL; 468 + } 468 469 469 470 if (!data->skip_autocfg) 470 471 dw8250_setup_port(&uart);