lkml.org 
[lkml]   [2012]   [Apr]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH v3 1/3] tegra, serial8250: add ->handle_break() uart_port op
    From
    Date
    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@intel.com>
    Cc: Colin Cross <ccross@android.com>
    Cc: Olof Johansson <olof@lixom.net>
    Cc: Stephen Warren <swarren@nvidia.com>
    Cc: Grant Likely <grant.likely@secretlab.ca>
    Cc: 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>
    ---
    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) {


    \
     
     \ /
      Last update: 2012-04-09 21:35    [W:0.041 / U:0.088 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site