| From 7dec2c8e8106f9d403696a7e361e4b7ecbc4194e Mon Sep 17 00:00:00 2001 |
| From: Paul Mundt <lethal@linux-sh.org> |
| Date: Wed, 8 Jun 2011 18:19:37 +0900 |
| Subject: serial: sh-sci: Generalize overrun handling. |
| |
| This consolidates all of the broken out overrun handling and ensures that |
| we have sensible defaults per-port type, in addition to making sure that |
| overruns are flagged appropriately in the error mask for parts that |
| haven't explicitly disabled support for it. |
| |
| Signed-off-by: Paul Mundt <lethal@linux-sh.org> |
| (cherry picked from commit debf9507166eede1e676d27d3298cdfb27399cb4) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| drivers/tty/serial/sh-sci.c | 51 +++++++++++++++++++++++++++++++++++++----- |
| drivers/tty/serial/sh-sci.h | 52 ++----------------------------------------- |
| include/linux/serial_sci.h | 30 +++++++++++++++++++++++++ |
| 3 files changed, 77 insertions(+), 56 deletions(-) |
| |
| diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c |
| index 5174d2f..b2c424b 100644 |
| --- a/drivers/tty/serial/sh-sci.c |
| +++ b/drivers/tty/serial/sh-sci.c |
| @@ -563,13 +563,19 @@ static int sci_handle_errors(struct uart_port *port) |
| int copied = 0; |
| unsigned short status = sci_in(port, SCxSR); |
| struct tty_struct *tty = port->state->port.tty; |
| + struct sci_port *s = to_sci_port(port); |
| |
| - if (status & SCxSR_ORER(port)) { |
| - /* overrun error */ |
| - if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) |
| - copied++; |
| + /* |
| + * Handle overruns, if supported. |
| + */ |
| + if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) { |
| + if (status & (1 << s->cfg->overrun_bit)) { |
| + /* overrun error */ |
| + if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) |
| + copied++; |
| |
| - dev_notice(port->dev, "overrun error"); |
| + dev_notice(port->dev, "overrun error"); |
| + } |
| } |
| |
| if (status & SCxSR_FER(port)) { |
| @@ -617,12 +623,19 @@ static int sci_handle_errors(struct uart_port *port) |
| static int sci_handle_fifo_overrun(struct uart_port *port) |
| { |
| struct tty_struct *tty = port->state->port.tty; |
| + struct sci_port *s = to_sci_port(port); |
| int copied = 0; |
| |
| + /* |
| + * XXX: Technically not limited to non-SCIFs, it's simply the |
| + * SCLSR check that is for the moment SCIF-specific. This |
| + * probably wants to be revisited for SCIFA/B as well as for |
| + * factoring in SCI overrun detection. |
| + */ |
| if (port->type != PORT_SCIF) |
| return 0; |
| |
| - if ((sci_in(port, SCLSR) & SCIF_ORER) != 0) { |
| + if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) { |
| sci_out(port, SCLSR, 0); |
| |
| tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
| @@ -1760,6 +1773,32 @@ static int __devinit sci_init_single(struct platform_device *dev, |
| sci_port->break_timer.function = sci_break_timer; |
| init_timer(&sci_port->break_timer); |
| |
| + /* |
| + * Establish some sensible defaults for the error detection. |
| + */ |
| + if (!p->error_mask) |
| + p->error_mask = (p->type == PORT_SCI) ? |
| + SCI_DEFAULT_ERROR_MASK : SCIF_DEFAULT_ERROR_MASK; |
| + |
| + /* |
| + * Establish sensible defaults for the overrun detection, unless |
| + * the part has explicitly disabled support for it. |
| + */ |
| + if (p->overrun_bit != SCIx_NOT_SUPPORTED) { |
| + if (p->type == PORT_SCI) |
| + p->overrun_bit = 5; |
| + else if (p->scbrr_algo_id == SCBRR_ALGO_4) |
| + p->overrun_bit = 9; |
| + else |
| + p->overrun_bit = 0; |
| + |
| + /* |
| + * Make the error mask inclusive of overrun detection, if |
| + * supported. |
| + */ |
| + p->error_mask |= (1 << p->overrun_bit); |
| + } |
| + |
| sci_port->cfg = p; |
| |
| port->mapbase = p->mapbase; |
| diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h |
| index a64beaf..a2f69f8 100644 |
| --- a/drivers/tty/serial/sh-sci.h |
| +++ b/drivers/tty/serial/sh-sci.h |
| @@ -19,11 +19,9 @@ |
| defined(CONFIG_ARCH_SH7372) |
| # define PORT_PTCR 0xA405011EUL |
| # define PORT_PVCR 0xA4050122UL |
| -# define SCIF_ORER 0x0200 /* overrun error bit */ |
| #elif defined(CONFIG_SH_RTS7751R2D) |
| # define SCSPTR1 0xFFE0001C /* 8 bit SCIF */ |
| # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ |
| defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ |
| defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ |
| @@ -32,15 +30,12 @@ |
| defined(CONFIG_CPU_SUBTYPE_SH7751R) |
| # define SCSPTR1 0xffe0001c /* 8 bit SCI */ |
| # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7760) |
| # define SCSPTR0 0xfe600024 /* 16 bit SCIF */ |
| # define SCSPTR1 0xfe610024 /* 16 bit SCIF */ |
| # define SCSPTR2 0xfe620024 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) |
| # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| # define PACR 0xa4050100 |
| # define PBCR 0xa4050102 |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7343) |
| @@ -48,35 +43,24 @@ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7722) |
| # define PWDR 0xA4050166 |
| # define PSCR 0xA405011E |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7366) |
| # define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ |
| # define SCSPTR0 SCPDR0 |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7723) |
| # define SCSPTR0 0xa4050160 |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| -#elif defined(CONFIG_CPU_SUBTYPE_SH7724) |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) |
| # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7757) |
| # define SCSPTR0 0xfe4b0020 |
| -# define SCIF_ORER 0x0001 |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7763) |
| # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7770) |
| # define SCSPTR0 0xff923020 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7780) |
| # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* Overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ |
| defined(CONFIG_CPU_SUBTYPE_SH7786) |
| # define SCSPTR0 0xffea0024 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* Overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ |
| defined(CONFIG_CPU_SUBTYPE_SH7203) || \ |
| defined(CONFIG_CPU_SUBTYPE_SH7206) || \ |
| @@ -84,36 +68,12 @@ |
| # define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7619) |
| # define SCSPTR0 0xf8400020 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* overrun error bit */ |
| #elif defined(CONFIG_CPU_SUBTYPE_SHX3) |
| # define SCSPTR0 0xffc30020 /* 16 bit SCIF */ |
| -# define SCIF_ORER 0x0001 /* Overrun error bit */ |
| #else |
| # error CPU subtype not defined |
| #endif |
| |
| -/* SCxSR SCI */ |
| -#define SCI_TDRE 0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
| -#define SCI_RDRF 0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
| -#define SCI_ORER 0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
| -#define SCI_FER 0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
| -#define SCI_PER 0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
| -#define SCI_TEND 0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
| -/* SCI_MPB 0x02 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
| -/* SCI_MPBT 0x01 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
| - |
| -#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER) |
| - |
| -/* SCxSR SCIF */ |
| -#define SCIF_ER 0x0080 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ |
| -#define SCIF_TEND 0x0040 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ |
| -#define SCIF_TDFE 0x0020 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ |
| -#define SCIF_BRK 0x0010 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ |
| -#define SCIF_FER 0x0008 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ |
| -#define SCIF_PER 0x0004 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ |
| -#define SCIF_RDF 0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ |
| -#define SCIF_DR 0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ |
| - |
| #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
| defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
| defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
| @@ -121,35 +81,27 @@ |
| defined(CONFIG_ARCH_SH7367) || \ |
| defined(CONFIG_ARCH_SH7377) || \ |
| defined(CONFIG_ARCH_SH7372) |
| -# define SCIF_ORER 0x0200 |
| -# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) |
| # define SCIF_RFDC_MASK 0x007f |
| # define SCIF_TXROOM_MAX 64 |
| #elif defined(CONFIG_CPU_SUBTYPE_SH7763) |
| -# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK ) |
| # define SCIF_RFDC_MASK 0x007f |
| # define SCIF_TXROOM_MAX 64 |
| /* SH7763 SCIF2 support */ |
| # define SCIF2_RFDC_MASK 0x001f |
| # define SCIF2_TXROOM_MAX 16 |
| #else |
| -# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) |
| # define SCIF_RFDC_MASK 0x001f |
| # define SCIF_TXROOM_MAX 16 |
| #endif |
| |
| -#ifndef SCIF_ORER |
| -#define SCIF_ORER 0x0000 |
| -#endif |
| - |
| #define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND) |
| -#define SCxSR_ERRORS(port) (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS) |
| #define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF) |
| #define SCxSR_TDxE(port) (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE) |
| #define SCxSR_FER(port) (((port)->type == PORT_SCI) ? SCI_FER : SCIF_FER) |
| #define SCxSR_PER(port) (((port)->type == PORT_SCI) ? SCI_PER : SCIF_PER) |
| #define SCxSR_BRK(port) (((port)->type == PORT_SCI) ? 0x00 : SCIF_BRK) |
| -#define SCxSR_ORER(port) (((port)->type == PORT_SCI) ? SCI_ORER : SCIF_ORER) |
| + |
| +#define SCxSR_ERRORS(port) (to_sci_port(port)->cfg->error_mask) |
| |
| #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
| defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
| diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h |
| index a2afc9f..5fac3bc 100644 |
| --- a/include/linux/serial_sci.h |
| +++ b/include/linux/serial_sci.h |
| @@ -8,6 +8,8 @@ |
| * Generic header for SuperH SCI(F) (used by sh/sh64/h8300 and related parts) |
| */ |
| |
| +#define SCIx_NOT_SUPPORTED (-1) |
| + |
| enum { |
| SCBRR_ALGO_1, /* ((clk + 16 * bps) / (16 * bps) - 1) */ |
| SCBRR_ALGO_2, /* ((clk + 16 * bps) / (32 * bps) - 1) */ |
| @@ -25,6 +27,28 @@ enum { |
| #define SCSCR_CKE1 (1 << 1) |
| #define SCSCR_CKE0 (1 << 0) |
| |
| +/* SCxSR SCI */ |
| +#define SCI_TDRE 0x80 |
| +#define SCI_RDRF 0x40 |
| +#define SCI_ORER 0x20 |
| +#define SCI_FER 0x10 |
| +#define SCI_PER 0x08 |
| +#define SCI_TEND 0x04 |
| + |
| +#define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER) |
| + |
| +/* SCxSR SCIF */ |
| +#define SCIF_ER 0x0080 |
| +#define SCIF_TEND 0x0040 |
| +#define SCIF_TDFE 0x0020 |
| +#define SCIF_BRK 0x0010 |
| +#define SCIF_FER 0x0008 |
| +#define SCIF_PER 0x0004 |
| +#define SCIF_RDF 0x0002 |
| +#define SCIF_DR 0x0001 |
| + |
| +#define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) |
| + |
| /* Offsets into the sci_port->irqs array */ |
| enum { |
| SCIx_ERI_IRQ, |
| @@ -56,6 +80,12 @@ struct plat_sci_port { |
| unsigned int scbrr_algo_id; /* SCBRR calculation algo */ |
| unsigned int scscr; /* SCSCR initialization */ |
| |
| + /* |
| + * Platform overrides if necessary, defaults otherwise. |
| + */ |
| + int overrun_bit; |
| + unsigned int error_mask; |
| + |
| struct device *dma_dev; |
| |
| unsigned int dma_slave_tx; |
| -- |
| 1.7.10 |
| |