diff options
author | Dan Williams <dan.j.williams@intel.com> | 2012-04-10 17:10:53 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-18 18:07:53 -0400 |
commit | bf03f65b7967df5807ddef7b99f8a41d4c94fc70 (patch) | |
tree | 558ae56db6ddedae03eee1bc569321d8ab571d0a | |
parent | 7c77c8decfd14a611ddcba071782a9520e4bb3f8 (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.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-paz00.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-seaboard.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-trimslice.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250.c | 34 | ||||
-rw-r--r-- | drivers/tty/serial/of_serial.c | 26 | ||||
-rw-r--r-- | include/linux/of_serial.h | 17 | ||||
-rw-r--r-- | include/linux/serial_8250.h | 1 | ||||
-rw-r--r-- | include/linux/serial_core.h | 5 |
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 | */ | ||
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 | * 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 | ||
31 | void 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 */ | ||
47 | EXPORT_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 | ||
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 */ | ||
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) | |||
533 | static inline int uart_handle_break(struct uart_port *port) | 534 | static 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) { |