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>
This commit is contained in:
parent
7c77c8decf
commit
bf03f65b79
9 changed files with 61 additions and 31 deletions
|
@ -19,6 +19,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/of_serial.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/pda_power.h>
|
||||
|
@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
|
|||
.irq = INT_UARTD,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
|
||||
.type = PORT_TEGRA,
|
||||
.handle_break = tegra_serial_handle_break,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = 216000000,
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/of_serial.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
|
@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
|
|||
.irq = INT_UARTA,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
|
||||
.type = PORT_TEGRA,
|
||||
.handle_break = tegra_serial_handle_break,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = 216000000,
|
||||
|
@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
|
|||
.irq = INT_UARTC,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
|
||||
.type = PORT_TEGRA,
|
||||
.handle_break = tegra_serial_handle_break,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = 216000000,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/of_serial.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
|
@ -47,6 +48,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
|
|||
/* Memory and IRQ filled in before registration */
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
|
||||
.type = PORT_TEGRA,
|
||||
.handle_break = tegra_serial_handle_break,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = 216000000,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/of_serial.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
|
@ -48,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
|
|||
.irq = INT_UARTA,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
|
||||
.type = PORT_TEGRA,
|
||||
.handle_break = tegra_serial_handle_break,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = 216000000,
|
||||
|
|
|
@ -1331,27 +1331,6 @@ static void serial8250_enable_ms(struct uart_port *port)
|
|||
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
|
||||
* value, and returns the remaining LSR bits not handled
|
||||
|
@ -1386,19 +1365,9 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
|
|||
up->lsr_saved_flags = 0;
|
||||
|
||||
if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
|
||||
/*
|
||||
* For statistics only
|
||||
*/
|
||||
if (lsr & UART_LSR_BI) {
|
||||
lsr &= ~(UART_LSR_FE | UART_LSR_PE);
|
||||
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
|
||||
* here because otherwise the break
|
||||
|
@ -3037,6 +3006,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
|
|||
port.serial_in = p->serial_in;
|
||||
port.serial_out = p->serial_out;
|
||||
port.handle_irq = p->handle_irq;
|
||||
port.handle_break = p->handle_break;
|
||||
port.set_termios = p->set_termios;
|
||||
port.pm = p->pm;
|
||||
port.dev = &dev->dev;
|
||||
|
@ -3209,6 +3179,8 @@ int serial8250_register_port(struct uart_port *port)
|
|||
uart->port.set_termios = port->set_termios;
|
||||
if (port->pm)
|
||||
uart->port.pm = port->pm;
|
||||
if (port->handle_break)
|
||||
uart->port.handle_break = port->handle_break;
|
||||
|
||||
if (serial8250_isa_config != NULL)
|
||||
serial8250_isa_config(0, &uart->port,
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_serial.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/nwpserial.h>
|
||||
|
||||
|
@ -24,6 +27,26 @@ struct of_serial_info {
|
|||
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
|
||||
*/
|
||||
|
@ -84,6 +107,9 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
|
|||
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||
port->dev = &ofdev->dev;
|
||||
|
||||
if (type == PORT_TEGRA)
|
||||
port->handle_break = tegra_serial_handle_break;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
17
include/linux/of_serial.h
Normal file
17
include/linux/of_serial.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#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 {
|
|||
int (*handle_irq)(struct uart_port *);
|
||||
void (*pm)(struct uart_port *, unsigned int state,
|
||||
unsigned old);
|
||||
void (*handle_break)(struct uart_port *);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -310,6 +310,7 @@ struct uart_port {
|
|||
int (*handle_irq)(struct uart_port *);
|
||||
void (*pm)(struct uart_port *, unsigned int state,
|
||||
unsigned int old);
|
||||
void (*handle_break)(struct uart_port *);
|
||||
unsigned int irq; /* irq number */
|
||||
unsigned long irqflags; /* irq flags */
|
||||
unsigned int uartclk; /* base uart clock */
|
||||
|
@ -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)
|
||||
{
|
||||
struct uart_state *state = port->state;
|
||||
|
||||
if (port->handle_break)
|
||||
port->handle_break(port);
|
||||
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
if (port->cons && port->cons->index == port->line) {
|
||||
if (!port->sysrq) {
|
||||
|
|
Loading…
Reference in a new issue