[ adding Arnd ] On Mon, Apr 9, 2012 at 12:48 PM, Dan Williams <dan.j.williams@xxxxxxxxx> wrote: > 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 (CONFIG_TEGRA_SERIAL, > 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@xxxxxxxxx> > Cc: Colin Cross <ccross@xxxxxxxxxxx> > Cc: Olof Johansson <olof@xxxxxxxxx> > Cc: Stephen Warren <swarren@xxxxxxxxxx> > Cc: Grant Likely <grant.likely@xxxxxxxxxxxx> > Cc: Arnd Bergmann arnd@xxxxxxxx Sorry, messed up Arnd's address, checkpatch would have caught this for me... > Acked-by: Sudhakar Mamillapalli <sudhakar@xxxxxx> > Reported-by: Alan Cox <alan@xxxxxxxxxxxxxxxxxxx> > Acked-by: Alan Cox <alan@xxxxxxxxxxxxxxx> > Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx> > --- > arch/arm/configs/tegra_defconfig | 1 + > arch/arm/mach-tegra/board-harmony.c | 4 ++++ > arch/arm/mach-tegra/board-paz00.c | 5 +++++ > arch/arm/mach-tegra/board-seaboard.c | 4 ++++ > arch/arm/mach-tegra/board-trimslice.c | 4 ++++ > arch/arm/mach-tegra/devices.h | 1 - > drivers/tty/serial/8250/8250.c | 34 +++------------------------------ > drivers/tty/serial/Kconfig | 8 ++++++++ > drivers/tty/serial/of_serial.c | 25 ++++++++++++++++++++++++ > include/linux/of_serial.h | 17 +++++++++++++++++ > include/linux/serial_8250.h | 1 + > include/linux/serial_core.h | 5 +++++ > 12 files changed, 77 insertions(+), 32 deletions(-) > create mode 100644 include/linux/of_serial.h > > diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig > index 351d670..de7288a 100644 > --- a/arch/arm/configs/tegra_defconfig > +++ b/arch/arm/configs/tegra_defconfig > @@ -97,6 +97,7 @@ CONFIG_INPUT_EVDEV=y > CONFIG_SERIAL_8250=y > CONFIG_SERIAL_8250_CONSOLE=y > CONFIG_SERIAL_OF_PLATFORM=y > +CONFIG_SERIAL_TEGRA=y > # CONFIG_HW_RANDOM is not set > CONFIG_I2C=y > # CONFIG_I2C_COMPAT is not set > diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c > index c00aadb..b8ceac3 100644 > --- a/arch/arm/mach-tegra/board-harmony.c > +++ b/arch/arm/mach-tegra/board-harmony.c > @@ -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, > @@ -115,7 +117,9 @@ static void __init harmony_i2c_init(void) > } > > static struct platform_device *harmony_devices[] __initdata = { > +#if IS_ENABLED(CONFIG_SERIAL_TEGRA) > &debug_uart, > +#endif > &tegra_sdhci_device1, > &tegra_sdhci_device2, > &tegra_sdhci_device4, > diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c > index 330afdf..1113dab 100644 > --- a/arch/arm/mach-tegra/board-paz00.c > +++ b/arch/arm/mach-tegra/board-paz00.c > @@ -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, > @@ -142,7 +145,9 @@ static struct platform_device gpio_keys_device = { > }; > > static struct platform_device *paz00_devices[] __initdata = { > +#if IS_ENABLED(CONFIG_SERIAL_TEGRA) > &debug_uart, > +#endif > &tegra_sdhci_device4, > &tegra_sdhci_device1, > &wifi_rfkill_device, > diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c > index d669847..59a30ab 100644 > --- a/arch/arm/mach-tegra/board-seaboard.c > +++ b/arch/arm/mach-tegra/board-seaboard.c > @@ -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, > @@ -145,7 +147,9 @@ static struct platform_device seaboard_audio_device = { > }; > > static struct platform_device *seaboard_devices[] __initdata = { > +#if IS_ENABLED(CONFIG_SERIAL_TEGRA) > &debug_uart, > +#endif > &tegra_pmu_device, > &tegra_sdhci_device4, > &tegra_sdhci_device3, > diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c > index cd52820..b156f55 100644 > --- a/arch/arm/mach-tegra/board-trimslice.c > +++ b/arch/arm/mach-tegra/board-trimslice.c > @@ -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, > @@ -81,7 +83,9 @@ static struct platform_device trimslice_audio_device = { > }; > > static struct platform_device *trimslice_devices[] __initdata = { > +#if IS_ENABLED(CONFIG_SERIAL_TEGRA) > &debug_uart, > +#endif > &tegra_sdhci_device1, > &tegra_sdhci_device4, > &tegra_i2s_device1, > diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h > index ec45567..6e5f852 100644 > --- a/arch/arm/mach-tegra/devices.h > +++ b/arch/arm/mach-tegra/devices.h > @@ -53,5 +53,4 @@ extern struct platform_device tegra_i2s_device1; > extern struct platform_device tegra_i2s_device2; > extern struct platform_device tegra_das_device; > extern struct platform_device tegra_pcm_device; > - > #endif > diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c > index 5c27f7e..cbd94c3 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) > } > > /* > - * 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 > * by this Rx routine. > @@ -1386,20 +1365,10 @@ 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 > * may get masked by ignore_status_mask > @@ -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, > diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig > index 665beb6..33fa6ec 100644 > --- a/drivers/tty/serial/Kconfig > +++ b/drivers/tty/serial/Kconfig > @@ -380,6 +380,14 @@ config SERIAL_PXA_CONSOLE > your boot loader (lilo or loadlin) about how to pass options to the > kernel at boot time.) > > +# FIXME remove this option when Tegra completes conversion to open firmware > +config SERIAL_TEGRA > + bool "Tegra serial port support" > + depends on SERIAL_OF_PLATFORM=y > + help > + If you have a machine based on NVIDIA Tegra you can enable its > + onboard serial ports by enabling this option. > + > config SERIAL_SA1100 > bool "SA1100 serial port support" > depends on ARM && ARCH_SA1100 > diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c > index e8c9cee..b692528 100644 > --- a/drivers/tty/serial/of_serial.c > +++ b/drivers/tty/serial/of_serial.c > @@ -12,8 +12,10 @@ > #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_platform.h> > @@ -24,6 +26,26 @@ struct of_serial_info { > int line; > }; > > +#if IS_ENABLED(CONFIG_SERIAL_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 +106,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; > } > > diff --git a/include/linux/of_serial.h b/include/linux/of_serial.h > new file mode 100644 > index 0000000..2035d96 > --- /dev/null > +++ b/include/linux/of_serial.h > @@ -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. > + */ > +#if IS_ENABLED(CONFIG_SERIAL_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 */ > diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h > index 8f012f8..a522fd9 100644 > --- a/include/linux/serial_8250.h > +++ b/include/linux/serial_8250.h > @@ -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 *); > }; > > /* > diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h > index 2db407a..65db992 100644 > --- a/include/linux/serial_core.h > +++ b/include/linux/serial_core.h > @@ -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) { > -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html