aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-04-10 17:10:53 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-18 18:07:53 -0400
commitbf03f65b7967df5807ddef7b99f8a41d4c94fc70 (patch)
tree558ae56db6ddedae03eee1bc569321d8ab571d0a
parent7c77c8decfd14a611ddcba071782a9520e4bb3f8 (diff)
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>
-rw-r--r--arch/arm/mach-tegra/board-harmony.c2
-rw-r--r--arch/arm/mach-tegra/board-paz00.c3
-rw-r--r--arch/arm/mach-tegra/board-seaboard.c2
-rw-r--r--arch/arm/mach-tegra/board-trimslice.c2
-rw-r--r--drivers/tty/serial/8250/8250.c34
-rw-r--r--drivers/tty/serial/of_serial.c26
-rw-r--r--include/linux/of_serial.h17
-rw-r--r--include/linux/serial_8250.h1
-rw-r--r--include/linux/serial_core.h5
9 files changed, 61 insertions, 31 deletions
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index c00aadb01e09..222182e00226 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -19,6 +19,7 @@
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/serial_8250.h> 21#include <linux/serial_8250.h>
22#include <linux/of_serial.h>
22#include <linux/clk.h> 23#include <linux/clk.h>
23#include <linux/dma-mapping.h> 24#include <linux/dma-mapping.h>
24#include <linux/pda_power.h> 25#include <linux/pda_power.h>
@@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
52 .irq = INT_UARTD, 53 .irq = INT_UARTD,
53 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 54 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
54 .type = PORT_TEGRA, 55 .type = PORT_TEGRA,
56 .handle_break = tegra_serial_handle_break,
55 .iotype = UPIO_MEM, 57 .iotype = UPIO_MEM,
56 .regshift = 2, 58 .regshift = 2,
57 .uartclk = 216000000, 59 .uartclk = 216000000,
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 330afdfa2475..d0735c70d688 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -21,6 +21,7 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/serial_8250.h> 23#include <linux/serial_8250.h>
24#include <linux/of_serial.h>
24#include <linux/clk.h> 25#include <linux/clk.h>
25#include <linux/dma-mapping.h> 26#include <linux/dma-mapping.h>
26#include <linux/gpio_keys.h> 27#include <linux/gpio_keys.h>
@@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
55 .irq = INT_UARTA, 56 .irq = INT_UARTA,
56 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 57 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
57 .type = PORT_TEGRA, 58 .type = PORT_TEGRA,
59 .handle_break = tegra_serial_handle_break,
58 .iotype = UPIO_MEM, 60 .iotype = UPIO_MEM,
59 .regshift = 2, 61 .regshift = 2,
60 .uartclk = 216000000, 62 .uartclk = 216000000,
@@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
65 .irq = INT_UARTC, 67 .irq = INT_UARTC,
66 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 68 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
67 .type = PORT_TEGRA, 69 .type = PORT_TEGRA,
70 .handle_break = tegra_serial_handle_break,
68 .iotype = UPIO_MEM, 71 .iotype = UPIO_MEM,
69 .regshift = 2, 72 .regshift = 2,
70 .uartclk = 216000000, 73 .uartclk = 216000000,
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index d669847f0485..5b687b8258c0 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -18,6 +18,7 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/serial_8250.h> 20#include <linux/serial_8250.h>
21#include <linux/of_serial.h>
21#include <linux/i2c.h> 22#include <linux/i2c.h>
22#include <linux/delay.h> 23#include <linux/delay.h>
23#include <linux/input.h> 24#include <linux/input.h>
@@ -47,6 +48,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
47 /* Memory and IRQ filled in before registration */ 48 /* Memory and IRQ filled in before registration */
48 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 49 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
49 .type = PORT_TEGRA, 50 .type = PORT_TEGRA,
51 .handle_break = tegra_serial_handle_break,
50 .iotype = UPIO_MEM, 52 .iotype = UPIO_MEM,
51 .regshift = 2, 53 .regshift = 2,
52 .uartclk = 216000000, 54 .uartclk = 216000000,
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index cd52820a3e37..f7358586b523 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -22,6 +22,7 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/serial_8250.h> 24#include <linux/serial_8250.h>
25#include <linux/of_serial.h>
25#include <linux/io.h> 26#include <linux/io.h>
26#include <linux/i2c.h> 27#include <linux/i2c.h>
27#include <linux/gpio.h> 28#include <linux/gpio.h>
@@ -48,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
48 .irq = INT_UARTA, 49 .irq = INT_UARTA,
49 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 50 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
50 .type = PORT_TEGRA, 51 .type = PORT_TEGRA,
52 .handle_break = tegra_serial_handle_break,
51 .iotype = UPIO_MEM, 53 .iotype = UPIO_MEM,
52 .regshift = 2, 54 .regshift = 2,
53 .uartclk = 216000000, 55 .uartclk = 216000000,
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 5b149b466ec8..dffd623b7974 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -1332,27 +1332,6 @@ static void serial8250_enable_ms(struct uart_port *port)
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 */
1340static 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 * serial8250_rx_chars: processes according to the passed in LSR 1335 * serial8250_rx_chars: processes according to the passed in LSR
1357 * value, and returns the remaining LSR bits not handled 1336 * value, and returns the remaining LSR bits not handled
1358 * by this Rx routine. 1337 * by this Rx routine.
@@ -1386,20 +1365,10 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
1386 up->lsr_saved_flags = 0; 1365 up->lsr_saved_flags = 0;
1387 1366
1388 if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { 1367 if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
1389 /*
1390 * For statistics only
1391 */
1392 if (lsr & UART_LSR_BI) { 1368 if (lsr & UART_LSR_BI) {
1393 lsr &= ~(UART_LSR_FE | UART_LSR_PE); 1369 lsr &= ~(UART_LSR_FE | UART_LSR_PE);
1394 port->icount.brk++; 1370 port->icount.brk++;
1395 /* 1371 /*
1396 * If tegra port then clear the rx fifo to
1397 * accept another break/character.
1398 */
1399 if (port->type == PORT_TEGRA)
1400 clear_rx_fifo(up);
1401
1402 /*
1403 * We do the SysRQ and SAK checking 1372 * We do the SysRQ and SAK checking
1404 * here because otherwise the break 1373 * here because otherwise the break
1405 * may get masked by ignore_status_mask 1374 * may get masked by ignore_status_mask
@@ -3037,6 +3006,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
3037 port.serial_in = p->serial_in; 3006 port.serial_in = p->serial_in;
3038 port.serial_out = p->serial_out; 3007 port.serial_out = p->serial_out;
3039 port.handle_irq = p->handle_irq; 3008 port.handle_irq = p->handle_irq;
3009 port.handle_break = p->handle_break;
3040 port.set_termios = p->set_termios; 3010 port.set_termios = p->set_termios;
3041 port.pm = p->pm; 3011 port.pm = p->pm;
3042 port.dev = &dev->dev; 3012 port.dev = &dev->dev;
@@ -3209,6 +3179,8 @@ int serial8250_register_port(struct uart_port *port)
3209 uart->port.set_termios = port->set_termios; 3179 uart->port.set_termios = port->set_termios;
3210 if (port->pm) 3180 if (port->pm)
3211 uart->port.pm = port->pm; 3181 uart->port.pm = port->pm;
3182 if (port->handle_break)
3183 uart->port.handle_break = port->handle_break;
3212 3184
3213 if (serial8250_isa_config != NULL) 3185 if (serial8250_isa_config != NULL)
3214 serial8250_isa_config(0, &uart->port, 3186 serial8250_isa_config(0, &uart->port,
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index e8c9cee07d00..5410c0637266 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -12,10 +12,13 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/delay.h>
15#include <linux/serial_core.h> 16#include <linux/serial_core.h>
16#include <linux/serial_8250.h> 17#include <linux/serial_8250.h>
18#include <linux/serial_reg.h>
17#include <linux/of_address.h> 19#include <linux/of_address.h>
18#include <linux/of_irq.h> 20#include <linux/of_irq.h>
21#include <linux/of_serial.h>
19#include <linux/of_platform.h> 22#include <linux/of_platform.h>
20#include <linux/nwpserial.h> 23#include <linux/nwpserial.h>
21 24
@@ -24,6 +27,26 @@ struct of_serial_info {
24 int line; 27 int line;
25}; 28};
26 29
30#ifdef CONFIG_ARCH_TEGRA
31void tegra_serial_handle_break(struct uart_port *p)
32{
33 unsigned int status, tmout = 10000;
34
35 do {
36 status = p->serial_in(p, UART_LSR);
37 if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
38 status = p->serial_in(p, UART_RX);
39 else
40 break;
41 if (--tmout == 0)
42 break;
43 udelay(1);
44 } while (1);
45}
46/* FIXME remove this export when tegra finishes conversion to open firmware */
47EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
48#endif
49
27/* 50/*
28 * Fill a struct uart_port for a given device node 51 * Fill a struct uart_port for a given device node
29 */ 52 */
@@ -84,6 +107,9 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
84 | UPF_FIXED_PORT | UPF_FIXED_TYPE; 107 | UPF_FIXED_PORT | UPF_FIXED_TYPE;
85 port->dev = &ofdev->dev; 108 port->dev = &ofdev->dev;
86 109
110 if (type == PORT_TEGRA)
111 port->handle_break = tegra_serial_handle_break;
112
87 return 0; 113 return 0;
88} 114}
89 115
diff --git a/include/linux/of_serial.h b/include/linux/of_serial.h
new file mode 100644
index 000000000000..4a73ed80b4c0
--- /dev/null
+++ b/include/linux/of_serial.h
@@ -0,0 +1,17 @@
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
10extern void tegra_serial_handle_break(struct uart_port *port);
11#else
12static inline void tegra_serial_handle_break(struct uart_port *port)
13{
14}
15#endif
16
17#endif /* __LINUX_OF_SERIAL */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 8f012f8ac8e9..a522fd977aad 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -38,6 +38,7 @@ struct plat_serial8250_port {
38 int (*handle_irq)(struct uart_port *); 38 int (*handle_irq)(struct uart_port *);
39 void (*pm)(struct uart_port *, unsigned int state, 39 void (*pm)(struct uart_port *, unsigned int state,
40 unsigned old); 40 unsigned old);
41 void (*handle_break)(struct uart_port *);
41}; 42};
42 43
43/* 44/*
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index f51bf2e70c69..0dd752f3039d 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -310,6 +310,7 @@ struct uart_port {
310 int (*handle_irq)(struct uart_port *); 310 int (*handle_irq)(struct uart_port *);
311 void (*pm)(struct uart_port *, unsigned int state, 311 void (*pm)(struct uart_port *, unsigned int state,
312 unsigned int old); 312 unsigned int old);
313 void (*handle_break)(struct uart_port *);
313 unsigned int irq; /* irq number */ 314 unsigned int irq; /* irq number */
314 unsigned long irqflags; /* irq flags */ 315 unsigned long irqflags; /* irq flags */
315 unsigned int uartclk; /* base uart clock */ 316 unsigned int uartclk; /* base uart clock */
@@ -533,6 +534,10 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
533static inline int uart_handle_break(struct uart_port *port) 534static inline int uart_handle_break(struct uart_port *port)
534{ 535{
535 struct uart_state *state = port->state; 536 struct uart_state *state = port->state;
537
538 if (port->handle_break)
539 port->handle_break(port);
540
536#ifdef SUPPORT_SYSRQ 541#ifdef SUPPORT_SYSRQ
537 if (port->cons && port->cons->index == port->line) { 542 if (port->cons && port->cons->index == port->line) {
538 if (!port->sysrq) { 543 if (!port->sysrq) {