Commit bf03f65b authored by Dan Williams's avatar Dan Williams Committed by Greg Kroah-Hartman

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: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarSudhakar Mamillapalli <sudhakar@fb.com>
Reported-by: default avatarAlan Cox <alan@lxorguk.ukuu.org.uk>
Acked-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Acked-by: default avatarStephen Warren <swarren@wwwdotorg.org>
Tested-by: default avatarStephen Warren <swarren@wwwdotorg.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7c77c8de
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/of_serial.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/pda_power.h> #include <linux/pda_power.h>
...@@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { ...@@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.irq = INT_UARTD, .irq = INT_UARTD,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA, .type = PORT_TEGRA,
.handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM, .iotype = UPIO_MEM,
.regshift = 2, .regshift = 2,
.uartclk = 216000000, .uartclk = 216000000,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/of_serial.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
...@@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { ...@@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.irq = INT_UARTA, .irq = INT_UARTA,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA, .type = PORT_TEGRA,
.handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM, .iotype = UPIO_MEM,
.regshift = 2, .regshift = 2,
.uartclk = 216000000, .uartclk = 216000000,
...@@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { ...@@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.irq = INT_UARTC, .irq = INT_UARTC,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA, .type = PORT_TEGRA,
.handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM, .iotype = UPIO_MEM,
.regshift = 2, .regshift = 2,
.uartclk = 216000000, .uartclk = 216000000,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/of_serial.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/input.h> #include <linux/input.h>
...@@ -47,6 +48,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { ...@@ -47,6 +48,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
/* Memory and IRQ filled in before registration */ /* Memory and IRQ filled in before registration */
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA, .type = PORT_TEGRA,
.handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM, .iotype = UPIO_MEM,
.regshift = 2, .regshift = 2,
.uartclk = 216000000, .uartclk = 216000000,
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/of_serial.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h> #include <linux/gpio.h>
...@@ -48,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { ...@@ -48,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.irq = INT_UARTA, .irq = INT_UARTA,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA, .type = PORT_TEGRA,
.handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM, .iotype = UPIO_MEM,
.regshift = 2, .regshift = 2,
.uartclk = 216000000, .uartclk = 216000000,
......
...@@ -1331,27 +1331,6 @@ static void serial8250_enable_ms(struct uart_port *port) ...@@ -1331,27 +1331,6 @@ static void serial8250_enable_ms(struct uart_port *port)
serial_port_out(port, UART_IER, up->ier); serial_port_out(port, UART_IER, up->ier);
} }
/*
* Clear the Tegra rx fifo after a break
*
* FIXME: This needs to become a port specific callback once we have a
* framework for this
*/
static void clear_rx_fifo(struct uart_8250_port *up)
{
unsigned int status, tmout = 10000;
do {
status = serial_in(up, UART_LSR);
if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
status = serial_in(up, UART_RX);
else
break;
if (--tmout == 0)
break;
udelay(1);
} while (1);
}
/* /*
* serial8250_rx_chars: processes according to the passed in LSR * serial8250_rx_chars: processes according to the passed in LSR
* value, and returns the remaining LSR bits not handled * value, and returns the remaining LSR bits not handled
...@@ -1386,19 +1365,9 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) ...@@ -1386,19 +1365,9 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
up->lsr_saved_flags = 0; up->lsr_saved_flags = 0;
if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
/*
* For statistics only
*/
if (lsr & UART_LSR_BI) { if (lsr & UART_LSR_BI) {
lsr &= ~(UART_LSR_FE | UART_LSR_PE); lsr &= ~(UART_LSR_FE | UART_LSR_PE);
port->icount.brk++; port->icount.brk++;
/*
* If tegra port then clear the rx fifo to
* accept another break/character.
*/
if (port->type == PORT_TEGRA)
clear_rx_fifo(up);
/* /*
* We do the SysRQ and SAK checking * We do the SysRQ and SAK checking
* here because otherwise the break * here because otherwise the break
...@@ -3037,6 +3006,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) ...@@ -3037,6 +3006,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
port.serial_in = p->serial_in; port.serial_in = p->serial_in;
port.serial_out = p->serial_out; port.serial_out = p->serial_out;
port.handle_irq = p->handle_irq; port.handle_irq = p->handle_irq;
port.handle_break = p->handle_break;
port.set_termios = p->set_termios; port.set_termios = p->set_termios;
port.pm = p->pm; port.pm = p->pm;
port.dev = &dev->dev; port.dev = &dev->dev;
...@@ -3209,6 +3179,8 @@ int serial8250_register_port(struct uart_port *port) ...@@ -3209,6 +3179,8 @@ int serial8250_register_port(struct uart_port *port)
uart->port.set_termios = port->set_termios; uart->port.set_termios = port->set_termios;
if (port->pm) if (port->pm)
uart->port.pm = port->pm; uart->port.pm = port->pm;
if (port->handle_break)
uart->port.handle_break = port->handle_break;
if (serial8250_isa_config != NULL) if (serial8250_isa_config != NULL)
serial8250_isa_config(0, &uart->port, serial8250_isa_config(0, &uart->port,
......
...@@ -12,10 +12,13 @@ ...@@ -12,10 +12,13 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_serial.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/nwpserial.h> #include <linux/nwpserial.h>
...@@ -24,6 +27,26 @@ struct of_serial_info { ...@@ -24,6 +27,26 @@ struct of_serial_info {
int line; int line;
}; };
#ifdef CONFIG_ARCH_TEGRA
void tegra_serial_handle_break(struct uart_port *p)
{
unsigned int status, tmout = 10000;
do {
status = p->serial_in(p, UART_LSR);
if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
status = p->serial_in(p, UART_RX);
else
break;
if (--tmout == 0)
break;
udelay(1);
} while (1);
}
/* FIXME remove this export when tegra finishes conversion to open firmware */
EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
#endif
/* /*
* Fill a struct uart_port for a given device node * Fill a struct uart_port for a given device node
*/ */
...@@ -84,6 +107,9 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, ...@@ -84,6 +107,9 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
| UPF_FIXED_PORT | UPF_FIXED_TYPE; | UPF_FIXED_PORT | UPF_FIXED_TYPE;
port->dev = &ofdev->dev; port->dev = &ofdev->dev;
if (type == PORT_TEGRA)
port->handle_break = tegra_serial_handle_break;
return 0; return 0;
} }
......
#ifndef __LINUX_OF_SERIAL_H
#define __LINUX_OF_SERIAL_H
/*
* FIXME remove this file when tegra finishes conversion to open firmware,
* expectation is that all quirks will then be self-contained in
* drivers/tty/serial/of_serial.c.
*/
#ifdef CONFIG_ARCH_TEGRA
extern void tegra_serial_handle_break(struct uart_port *port);
#else
static inline void tegra_serial_handle_break(struct uart_port *port)
{
}
#endif
#endif /* __LINUX_OF_SERIAL */
...@@ -38,6 +38,7 @@ struct plat_serial8250_port { ...@@ -38,6 +38,7 @@ struct plat_serial8250_port {
int (*handle_irq)(struct uart_port *); int (*handle_irq)(struct uart_port *);
void (*pm)(struct uart_port *, unsigned int state, void (*pm)(struct uart_port *, unsigned int state,
unsigned old); unsigned old);
void (*handle_break)(struct uart_port *);
}; };
/* /*
......
...@@ -310,6 +310,7 @@ struct uart_port { ...@@ -310,6 +310,7 @@ struct uart_port {
int (*handle_irq)(struct uart_port *); int (*handle_irq)(struct uart_port *);
void (*pm)(struct uart_port *, unsigned int state, void (*pm)(struct uart_port *, unsigned int state,
unsigned int old); unsigned int old);
void (*handle_break)(struct uart_port *);
unsigned int irq; /* irq number */ unsigned int irq; /* irq number */
unsigned long irqflags; /* irq flags */ unsigned long irqflags; /* irq flags */
unsigned int uartclk; /* base uart clock */ unsigned int uartclk; /* base uart clock */
...@@ -533,6 +534,10 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) ...@@ -533,6 +534,10 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
static inline int uart_handle_break(struct uart_port *port) static inline int uart_handle_break(struct uart_port *port)
{ {
struct uart_state *state = port->state; struct uart_state *state = port->state;
if (port->handle_break)
port->handle_break(port);
#ifdef SUPPORT_SYSRQ #ifdef SUPPORT_SYSRQ
if (port->cons && port->cons->index == port->line) { if (port->cons && port->cons->index == port->line) {
if (!port->sysrq) { if (!port->sysrq) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment