From: Geert Uytterhoeven <geert+renesas@glider.be>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jiri Slaby <jslaby@suse.cz>
Cc: Magnus Damm <magnus.damm@gmail.com>,
Simon Horman <horms@verge.net.au>,
Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>,
Yoshinori Sato <ysato@users.sourceforge.jp>,
linux-serial@vger.kernel.org, linux-sh@vger.kernel.org,
Geert Uytterhoeven <geert+renesas@glider.be>
Subject: [PATCH/RFC 11/13] serial: sh-sci: Replace buggy big #ifdef by runtime logic
Date: Thu, 30 Apr 2015 18:21:35 +0200 [thread overview]
Message-ID: <1430410897-12770-12-git-send-email-geert+renesas@glider.be> (raw)
In-Reply-To: <1430410897-12770-1-git-send-email-geert+renesas@glider.be>
The #ifdef logic to clear SCxSR bits using RMW on SCIFA/SCIFB and SCIF
variants with some SCIFA features (sh7705/SH7720/sh7721) has several
drawbacks:
- It wasn't updated for newer R-Mobile variants (APE6),
- It doesn't correctly handle SoCs with both SCIF and SCIFA/B (e.g.
R-Car Gen2, but also legacy sh7723/sh7724),
- It doesn't play well with ARM multi-platform kernels: on R-Car Gen2,
SCIF/SCIFA/SCIFB/HSCIF were handled differently, depending on
whether r8a7740 or sh73a0 support was enabled or not,
Replace the #ifdef logic by runtime logic to fix this.
SCIFA/SCIFB and SCIF on sh7705/sh7720/sh7721 use RMW to clear error
bits, other variants use plain stores, as before.
Note that this changes behavior for SCIFA on sh7723/sh7724 (these SoCs
have both SCIF and SCIFA), which didn't use RMW before.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Question: Can we simplify the logic and use RMW everywhere?
We seem to have been using it fine with (H)SCIF on R-Car Gen2 running
multi-platform kernels.
---
drivers/tty/serial/sh-sci.c | 36 ++++++++++++++++++++++++++----------
drivers/tty/serial/sh-sci.h | 33 ++++++++-------------------------
2 files changed, 34 insertions(+), 35 deletions(-)
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index b74a644e4b044b8b..67f796b3f4d51a97 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -489,6 +489,22 @@ static void sci_port_disable(struct sci_port *sci_port)
pm_runtime_put_sync(sci_port->port.dev);
}
+static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask)
+{
+ if (port->type == PORT_SCI) {
+ /* Just store the mask */
+ serial_port_out(port, SCxSR, mask);
+ } else if (to_sci_port(port)->overrun_mask == SCIFA_ORER) {
+ /* SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 */
+ /* Only clear the status bits we want to clear */
+ serial_port_out(port, SCxSR,
+ serial_port_in(port, SCxSR) & mask);
+ } else {
+ /* Store the mask, clear parity/framing errors */
+ serial_port_out(port, SCxSR, mask & ~(SCIF_FERC | SCIF_PERC));
+ }
+}
+
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
#ifdef CONFIG_CONSOLE_POLL
@@ -500,7 +516,7 @@ static int sci_poll_get_char(struct uart_port *port)
do {
status = serial_port_in(port, SCxSR);
if (status & SCxSR_ERRORS(port)) {
- serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
continue;
}
break;
@@ -513,7 +529,7 @@ static int sci_poll_get_char(struct uart_port *port)
/* Dummy read */
serial_port_in(port, SCxSR);
- serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
return c;
}
@@ -528,7 +544,7 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
} while (!(status & SCxSR_TDxE(port)));
serial_port_out(port, SCxTDR, c);
- serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
+ sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
}
#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
@@ -655,7 +671,7 @@ static void sci_transmit_chars(struct uart_port *port)
port->icount.tx++;
} while (--count > 0);
- serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
@@ -666,7 +682,7 @@ static void sci_transmit_chars(struct uart_port *port)
if (port->type != PORT_SCI) {
serial_port_in(port, SCxSR); /* Dummy read */
- serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
}
ctrl |= SCSCR_TIE;
@@ -750,7 +766,7 @@ static void sci_receive_chars(struct uart_port *port)
}
serial_port_in(port, SCxSR); /* dummy read */
- serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
copied += count;
port->icount.rx += count;
@@ -761,7 +777,7 @@ static void sci_receive_chars(struct uart_port *port)
tty_flip_buffer_push(tport);
} else {
serial_port_in(port, SCxSR); /* dummy read */
- serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
}
}
@@ -982,14 +998,14 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr)
if (sci_handle_errors(port)) {
/* discard character in rx buffer */
serial_port_in(port, SCxSR);
- serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
}
} else {
sci_handle_fifo_overrun(port);
sci_rx_interrupt(irq, ptr);
}
- serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
/* Kick the transmission */
sci_tx_interrupt(irq, ptr);
@@ -1003,7 +1019,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
/* Handle BREAKs */
sci_handle_breaks(port);
- serial_port_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
+ sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
return IRQ_HANDLED;
}
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index 3393f67b4e843578..1e1edbd152673e8f 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -119,28 +119,11 @@ enum {
#define SCxSR_ERRORS(port) (to_sci_port(port)->error_mask)
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721) || \
- defined(CONFIG_ARCH_SH73A0) || \
- defined(CONFIG_ARCH_R8A7740)
-
-# define SCxSR_RDxF_CLEAR(port) \
- (serial_port_in(port, SCxSR) & SCIF_RDxF_CLEAR)
-# define SCxSR_ERROR_CLEAR(port) \
- (serial_port_in(port, SCxSR) & SCIF_ERROR_CLEAR)
-# define SCxSR_TDxE_CLEAR(port) \
- (serial_port_in(port, SCxSR) & SCIF_TDxE_CLEAR)
-# define SCxSR_BREAK_CLEAR(port) \
- (serial_port_in(port, SCxSR) & SCIF_BREAK_CLEAR)
-#else
-# define SCxSR_RDxF_CLEAR(port) \
- ((((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR) & 0xff)
-# define SCxSR_ERROR_CLEAR(port) \
- ((((port)->type == PORT_SCI) ? SCI_ERROR_CLEAR : SCIF_ERROR_CLEAR) & 0xff)
-# define SCxSR_TDxE_CLEAR(port) \
- ((((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR) & 0xff)
-# define SCxSR_BREAK_CLEAR(port) \
- ((((port)->type == PORT_SCI) ? SCI_BREAK_CLEAR : SCIF_BREAK_CLEAR) & 0xff)
-#endif
-
+#define SCxSR_RDxF_CLEAR(port) \
+ (((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR)
+#define SCxSR_ERROR_CLEAR(port) \
+ (((port)->type == PORT_SCI) ? SCI_ERROR_CLEAR : SCIF_ERROR_CLEAR)
+#define SCxSR_TDxE_CLEAR(port) \
+ (((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR)
+#define SCxSR_BREAK_CLEAR(port) \
+ (((port)->type == PORT_SCI) ? SCI_BREAK_CLEAR : SCIF_BREAK_CLEAR)
--
1.9.1
next prev parent reply other threads:[~2015-04-30 16:21 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-30 16:21 [PATCH/RFC 00/13] serial: sh-sci: Cleanups and bug fixes Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 01/13] serial: sh-sci: Move private definitions to private header file Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 02/13] serial: sh-sci: Add (H)SCIF RTS/CTS pin data register bit definitions Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 03/13] serial: sh-sci: Add SCIFA/B SCPCR register definitions Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 04/13] serial: sh-sci: Document remaining FIFO Control Register bits Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 05/13] serial: sh-sci: Standardize on using the BIT() macro to define register bits Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 06/13] serial: sh-sci: Replace hardcoded values in SCxSR_*_CLEAR macros Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 07/13] serial: sh-sci: Replace hardcoded overrun bit values Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 08/13] serial: sh-sci: Use the correct register for overrun checks Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 09/13] serial: sh-sci: Don't set SCLSR bits in the SCxSR error mask Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH 10/13] serial: sh-sci: Remove obsolete comment about overrun detection Geert Uytterhoeven
2015-04-30 16:21 ` Geert Uytterhoeven [this message]
2015-04-30 16:21 ` [PATCH/RFC 12/13] serial: sh-sci: Correct SCIF_ERROR_CLEAR for plain SCIF Geert Uytterhoeven
2015-04-30 16:21 ` [PATCH/RFC 13/13] serial: sh-sci: Correct FIFO stages on sh7705/sh7720/sh7721 Geert Uytterhoeven
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1430410897-12770-12-git-send-email-geert+renesas@glider.be \
--to=geert+renesas@glider.be \
--cc=gregkh@linuxfoundation.org \
--cc=horms@verge.net.au \
--cc=jslaby@suse.cz \
--cc=linux-serial@vger.kernel.org \
--cc=linux-sh@vger.kernel.org \
--cc=magnus.damm@gmail.com \
--cc=nobuhiro.iwamatsu.yj@renesas.com \
--cc=ysato@users.sourceforge.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).