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

tegra, serial8250: add ->handle_break() uart_port op

The "KT" serial port has another use case for a "received break" quirk,
so before adding another special case to the 8250 core take this
opportunity to push such quirks out of the core and into a uart_port op.

Stephen says:
"If the callback function is to no longer live in 8250.c itself,
arch/arm/mach-tegra/devices.c isn't logically a good place to put it,
and that file will be going away once we get rid of all the board files
and move solely to device tree."

...so since 8250_pci.c houses all the quirks for pci serial devices this
quirk is similarly housed in of_serial.c. Once the open firmware
conversion completes the infrastructure details
(include/linux/of_serial.h, and the export) can all be removed to make
this self contained to of_serial.c.

Cc: Nhan H Mai <nhan.h.mai@intel.com>
Cc: Colin Cross <ccross@android.com>
Cc: Olof Johansson <olof@lixom.net>
[stephen: kill CONFIG_SERIAL_TEGRA in favor just using CONFIG_ARCH_TEGRA]
Cc: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Sudhakar Mamillapalli <sudhakar@fb.com>
Reported-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Stephen Warren <swarren@wwwdotorg.org>
Tested-by: Stephen Warren <swarren@wwwdotorg.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Dan Williams and committed by
Greg Kroah-Hartman
bf03f65b 7c77c8de

+61 -31
+2
arch/arm/mach-tegra/board-harmony.c
··· 19 19 #include <linux/init.h> 20 20 #include <linux/platform_device.h> 21 21 #include <linux/serial_8250.h> 22 + #include <linux/of_serial.h> 22 23 #include <linux/clk.h> 23 24 #include <linux/dma-mapping.h> 24 25 #include <linux/pda_power.h> ··· 53 52 .irq = INT_UARTD, 54 53 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 55 54 .type = PORT_TEGRA, 55 + .handle_break = tegra_serial_handle_break, 56 56 .iotype = UPIO_MEM, 57 57 .regshift = 2, 58 58 .uartclk = 216000000,
+3
arch/arm/mach-tegra/board-paz00.c
··· 21 21 #include <linux/init.h> 22 22 #include <linux/platform_device.h> 23 23 #include <linux/serial_8250.h> 24 + #include <linux/of_serial.h> 24 25 #include <linux/clk.h> 25 26 #include <linux/dma-mapping.h> 26 27 #include <linux/gpio_keys.h> ··· 56 55 .irq = INT_UARTA, 57 56 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 58 57 .type = PORT_TEGRA, 58 + .handle_break = tegra_serial_handle_break, 59 59 .iotype = UPIO_MEM, 60 60 .regshift = 2, 61 61 .uartclk = 216000000, ··· 67 65 .irq = INT_UARTC, 68 66 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 69 67 .type = PORT_TEGRA, 68 + .handle_break = tegra_serial_handle_break, 70 69 .iotype = UPIO_MEM, 71 70 .regshift = 2, 72 71 .uartclk = 216000000,
+2
arch/arm/mach-tegra/board-seaboard.c
··· 18 18 #include <linux/init.h> 19 19 #include <linux/platform_device.h> 20 20 #include <linux/serial_8250.h> 21 + #include <linux/of_serial.h> 21 22 #include <linux/i2c.h> 22 23 #include <linux/delay.h> 23 24 #include <linux/input.h> ··· 48 47 /* Memory and IRQ filled in before registration */ 49 48 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 50 49 .type = PORT_TEGRA, 50 + .handle_break = tegra_serial_handle_break, 51 51 .iotype = UPIO_MEM, 52 52 .regshift = 2, 53 53 .uartclk = 216000000,
+2
arch/arm/mach-tegra/board-trimslice.c
··· 22 22 #include <linux/init.h> 23 23 #include <linux/platform_device.h> 24 24 #include <linux/serial_8250.h> 25 + #include <linux/of_serial.h> 25 26 #include <linux/io.h> 26 27 #include <linux/i2c.h> 27 28 #include <linux/gpio.h> ··· 49 48 .irq = INT_UARTA, 50 49 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 51 50 .type = PORT_TEGRA, 51 + .handle_break = tegra_serial_handle_break, 52 52 .iotype = UPIO_MEM, 53 53 .regshift = 2, 54 54 .uartclk = 216000000,
+3 -31
drivers/tty/serial/8250/8250.c
··· 1332 1332 } 1333 1333 1334 1334 /* 1335 - * Clear the Tegra rx fifo after a break 1336 - * 1337 - * FIXME: This needs to become a port specific callback once we have a 1338 - * framework for this 1339 - */ 1340 - static void clear_rx_fifo(struct uart_8250_port *up) 1341 - { 1342 - unsigned int status, tmout = 10000; 1343 - do { 1344 - status = serial_in(up, UART_LSR); 1345 - if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) 1346 - status = serial_in(up, UART_RX); 1347 - else 1348 - break; 1349 - if (--tmout == 0) 1350 - break; 1351 - udelay(1); 1352 - } while (1); 1353 - } 1354 - 1355 - /* 1356 1335 * serial8250_rx_chars: processes according to the passed in LSR 1357 1336 * value, and returns the remaining LSR bits not handled 1358 1337 * by this Rx routine. ··· 1365 1386 up->lsr_saved_flags = 0; 1366 1387 1367 1388 if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { 1368 - /* 1369 - * For statistics only 1370 - */ 1371 1389 if (lsr & UART_LSR_BI) { 1372 1390 lsr &= ~(UART_LSR_FE | UART_LSR_PE); 1373 1391 port->icount.brk++; 1374 - /* 1375 - * If tegra port then clear the rx fifo to 1376 - * accept another break/character. 1377 - */ 1378 - if (port->type == PORT_TEGRA) 1379 - clear_rx_fifo(up); 1380 - 1381 1392 /* 1382 1393 * We do the SysRQ and SAK checking 1383 1394 * here because otherwise the break ··· 3006 3037 port.serial_in = p->serial_in; 3007 3038 port.serial_out = p->serial_out; 3008 3039 port.handle_irq = p->handle_irq; 3040 + port.handle_break = p->handle_break; 3009 3041 port.set_termios = p->set_termios; 3010 3042 port.pm = p->pm; 3011 3043 port.dev = &dev->dev; ··· 3179 3209 uart->port.set_termios = port->set_termios; 3180 3210 if (port->pm) 3181 3211 uart->port.pm = port->pm; 3212 + if (port->handle_break) 3213 + uart->port.handle_break = port->handle_break; 3182 3214 3183 3215 if (serial8250_isa_config != NULL) 3184 3216 serial8250_isa_config(0, &uart->port,
+26
drivers/tty/serial/of_serial.c
··· 12 12 #include <linux/init.h> 13 13 #include <linux/module.h> 14 14 #include <linux/slab.h> 15 + #include <linux/delay.h> 15 16 #include <linux/serial_core.h> 16 17 #include <linux/serial_8250.h> 18 + #include <linux/serial_reg.h> 17 19 #include <linux/of_address.h> 18 20 #include <linux/of_irq.h> 21 + #include <linux/of_serial.h> 19 22 #include <linux/of_platform.h> 20 23 #include <linux/nwpserial.h> 21 24 ··· 26 23 int type; 27 24 int line; 28 25 }; 26 + 27 + #ifdef CONFIG_ARCH_TEGRA 28 + void tegra_serial_handle_break(struct uart_port *p) 29 + { 30 + unsigned int status, tmout = 10000; 31 + 32 + do { 33 + status = p->serial_in(p, UART_LSR); 34 + if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) 35 + status = p->serial_in(p, UART_RX); 36 + else 37 + break; 38 + if (--tmout == 0) 39 + break; 40 + udelay(1); 41 + } while (1); 42 + } 43 + /* FIXME remove this export when tegra finishes conversion to open firmware */ 44 + EXPORT_SYMBOL_GPL(tegra_serial_handle_break); 45 + #endif 29 46 30 47 /* 31 48 * Fill a struct uart_port for a given device node ··· 106 83 port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP 107 84 | UPF_FIXED_PORT | UPF_FIXED_TYPE; 108 85 port->dev = &ofdev->dev; 86 + 87 + if (type == PORT_TEGRA) 88 + port->handle_break = tegra_serial_handle_break; 109 89 110 90 return 0; 111 91 }
+17
include/linux/of_serial.h
··· 1 + #ifndef __LINUX_OF_SERIAL_H 2 + #define __LINUX_OF_SERIAL_H 3 + 4 + /* 5 + * FIXME remove this file when tegra finishes conversion to open firmware, 6 + * expectation is that all quirks will then be self-contained in 7 + * drivers/tty/serial/of_serial.c. 8 + */ 9 + #ifdef CONFIG_ARCH_TEGRA 10 + extern void tegra_serial_handle_break(struct uart_port *port); 11 + #else 12 + static inline void tegra_serial_handle_break(struct uart_port *port) 13 + { 14 + } 15 + #endif 16 + 17 + #endif /* __LINUX_OF_SERIAL */
+1
include/linux/serial_8250.h
··· 38 38 int (*handle_irq)(struct uart_port *); 39 39 void (*pm)(struct uart_port *, unsigned int state, 40 40 unsigned old); 41 + void (*handle_break)(struct uart_port *); 41 42 }; 42 43 43 44 /*
+5
include/linux/serial_core.h
··· 310 310 int (*handle_irq)(struct uart_port *); 311 311 void (*pm)(struct uart_port *, unsigned int state, 312 312 unsigned int old); 313 + void (*handle_break)(struct uart_port *); 313 314 unsigned int irq; /* irq number */ 314 315 unsigned long irqflags; /* irq flags */ 315 316 unsigned int uartclk; /* base uart clock */ ··· 534 533 static inline int uart_handle_break(struct uart_port *port) 535 534 { 536 535 struct uart_state *state = port->state; 536 + 537 + if (port->handle_break) 538 + port->handle_break(port); 539 + 537 540 #ifdef SUPPORT_SYSRQ 538 541 if (port->cons && port->cons->index == port->line) { 539 542 if (!port->sysrq) {