From: Bryan Wu <bryan.wu@analog.com>
To: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
Mike Frysinger <michael.frysinger@analog.com>,
Bryan Wu <bryan.wu@analog.com>
Subject: [PATCH 08/12] [Blackfin] serial driver: fix bug - cache the bits of the LSR on systems where the LSR is read-to-clear
Date: Wed, 30 Jan 2008 17:30:08 +0800 [thread overview]
Message-ID: <1201685412-29095-9-git-send-email-bryan.wu@analog.com> (raw)
In-Reply-To: <1201685412-29095-1-git-send-email-bryan.wu@analog.com>
From: Mike Frysinger <michael.frysinger@analog.com>
Cache the bits of the LSR on systems where the LSR is read-to-clear
so that we can safely read the LSR in random places. this fixes
older parts where break/framing/parity/overflow was not being detected
at all in PIO mode, and this fixes newer parts where
break/framing/parity/overflow was being reported all the time
without being cleared.
Signed-off-by: Mike Frysinger <michael.frysinger@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
drivers/serial/bfin_5xx.c | 10 +++++++---
include/asm-blackfin/mach-bf527/bfin_serial_5xx.h | 19 ++++++++++++++++++-
include/asm-blackfin/mach-bf533/bfin_serial_5xx.h | 19 ++++++++++++++++++-
include/asm-blackfin/mach-bf537/bfin_serial_5xx.h | 19 ++++++++++++++++++-
include/asm-blackfin/mach-bf548/bfin_serial_5xx.h | 1 +
include/asm-blackfin/mach-bf561/bfin_serial_5xx.h | 19 ++++++++++++++++++-
6 files changed, 80 insertions(+), 7 deletions(-)
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index ca9ceaa..af84984 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -216,8 +216,10 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
struct pt_regs *regs = get_irq_regs();
#endif
- ch = UART_GET_CHAR(uart);
status = UART_GET_LSR(uart);
+ UART_CLEAR_LSR(uart);
+
+ ch = UART_GET_CHAR(uart);
uart->port.icount.rx++;
#ifdef CONFIG_KGDB_UART
@@ -335,7 +337,7 @@ static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
struct bfin_serial_port *uart = dev_id;
spin_lock(&uart->port.lock);
- while ((UART_GET_IER(uart) & ERBFI) && (UART_GET_LSR(uart) & DR))
+ while (UART_GET_LSR(uart) & DR)
bfin_serial_rx_chars(uart);
spin_unlock(&uart->port.lock);
@@ -347,7 +349,7 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
struct bfin_serial_port *uart = dev_id;
spin_lock(&uart->port.lock);
- if ((UART_GET_IER(uart) & ETBEI) && (UART_GET_LSR(uart) & THRE))
+ if (UART_GET_LSR(uart) & THRE)
bfin_serial_tx_chars(uart);
spin_unlock(&uart->port.lock);
@@ -428,6 +430,8 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
int i, flg, status;
status = UART_GET_LSR(uart);
+ UART_CLEAR_LSR(uart);
+
uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE);;
if (status & BI) {
diff --git a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
index 15dbc21..233c585 100644
--- a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
@@ -23,7 +23,6 @@
#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR))
#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR))
#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
#define UART_PUT_CHAR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_THR), v)
@@ -58,6 +57,7 @@
struct bfin_serial_port {
struct uart_port port;
unsigned int old_status;
+ unsigned int lsr;
#ifdef CONFIG_SERIAL_BFIN_DMA
int tx_done;
int tx_count;
@@ -76,6 +76,23 @@ struct bfin_serial_port {
#endif
};
+/* The hardware clears the LSR bits upon read, so we need to cache
+ * some of the more fun bits in software so they don't get lost
+ * when checking the LSR in other code paths (TX).
+ */
+static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
+{
+ unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
+ uart->lsr |= (lsr & (BI|FE|PE|OE));
+ return lsr | uart->lsr;
+}
+
+static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+{
+ uart->lsr = 0;
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+}
+
struct bfin_serial_port bfin_serial_ports[NR_PORTS];
struct bfin_serial_res {
unsigned long uart_base_addr;
diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
index 7871d43..b619065 100644
--- a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
@@ -23,7 +23,6 @@
#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR))
#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR))
#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
#define UART_PUT_CHAR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_THR),v)
@@ -46,6 +45,7 @@
struct bfin_serial_port {
struct uart_port port;
unsigned int old_status;
+ unsigned int lsr;
#ifdef CONFIG_SERIAL_BFIN_DMA
int tx_done;
int tx_count;
@@ -64,6 +64,23 @@ struct bfin_serial_port {
#endif
};
+/* The hardware clears the LSR bits upon read, so we need to cache
+ * some of the more fun bits in software so they don't get lost
+ * when checking the LSR in other code paths (TX).
+ */
+static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
+{
+ unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
+ uart->lsr |= (lsr & (BI|FE|PE|OE));
+ return lsr | uart->lsr;
+}
+
+static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+{
+ uart->lsr = 0;
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+}
+
struct bfin_serial_port bfin_serial_ports[NR_PORTS];
struct bfin_serial_res {
unsigned long uart_base_addr;
diff --git a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
index 86e45c3..f18c517 100644
--- a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
@@ -23,7 +23,6 @@
#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR))
#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR))
#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
#define UART_PUT_CHAR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_THR),v)
@@ -58,6 +57,7 @@
struct bfin_serial_port {
struct uart_port port;
unsigned int old_status;
+ unsigned int lsr;
#ifdef CONFIG_SERIAL_BFIN_DMA
int tx_done;
int tx_count;
@@ -76,6 +76,23 @@ struct bfin_serial_port {
#endif
};
+/* The hardware clears the LSR bits upon read, so we need to cache
+ * some of the more fun bits in software so they don't get lost
+ * when checking the LSR in other code paths (TX).
+ */
+static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
+{
+ unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
+ uart->lsr |= (lsr & (BI|FE|PE|OE));
+ return lsr | uart->lsr;
+}
+
+static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+{
+ uart->lsr = 0;
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+}
+
struct bfin_serial_port bfin_serial_ports[NR_PORTS];
struct bfin_serial_res {
unsigned long uart_base_addr;
diff --git a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
index 3770aa3..8733d47 100644
--- a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
@@ -32,6 +32,7 @@
#define UART_PUT_DLH(uart,v) bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
#define UART_PUT_LSR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_LSR),v)
#define UART_PUT_LCR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
+#define UART_CLEAR_LSR(uart) bfin_write16(((uart)->port.membase + OFFSET_LSR), -1)
#define UART_PUT_GCTL(uart,v) bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
index 7871d43..b619065 100644
--- a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
@@ -23,7 +23,6 @@
#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR))
#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR))
#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
#define UART_PUT_CHAR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_THR),v)
@@ -46,6 +45,7 @@
struct bfin_serial_port {
struct uart_port port;
unsigned int old_status;
+ unsigned int lsr;
#ifdef CONFIG_SERIAL_BFIN_DMA
int tx_done;
int tx_count;
@@ -64,6 +64,23 @@ struct bfin_serial_port {
#endif
};
+/* The hardware clears the LSR bits upon read, so we need to cache
+ * some of the more fun bits in software so they don't get lost
+ * when checking the LSR in other code paths (TX).
+ */
+static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
+{
+ unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
+ uart->lsr |= (lsr & (BI|FE|PE|OE));
+ return lsr | uart->lsr;
+}
+
+static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+{
+ uart->lsr = 0;
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+}
+
struct bfin_serial_port bfin_serial_ports[NR_PORTS];
struct bfin_serial_res {
unsigned long uart_base_addr;
--
1.5.3.4
next prev parent reply other threads:[~2008-01-30 9:30 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-30 9:30 [PATCH 00/12] Blackfin serial driver updates Bryan Wu
2008-01-30 9:30 ` [PATCH 01/12] [8250 Serial Driver]: Added support for 8250-class UARTs in HV Sistemas H8606 board Bryan Wu
2008-01-30 9:30 ` [PATCH 02/12] [Blackfin] Serial driver: Fix bug - serial driver in PIO mode cant handle input very quickly Bryan Wu
2008-01-30 9:30 ` [PATCH 03/12] [Blackfin] serial driver: Clean up UART DMA code Bryan Wu
2008-01-30 9:30 ` [PATCH 04/12] [Blackfin] serial driver: Fix bug Free rx dma buffer in shutdown Bryan Wu
2008-01-30 9:30 ` [PATCH 05/12] [Blackfin] serial driver: Fix bug serial driver in DMA mode spams history to console on shell restart Bryan Wu
2008-01-30 9:30 ` [PATCH 06/12] [Blackfin] serial driver: fix bug - should not wait for the TFI bit, just clear it when tx stop Bryan Wu
2008-01-30 9:30 ` [PATCH 07/12] [Blackfin] serial driver: add extra IRQ flag for 8250 serial driver Bryan Wu
2008-01-30 9:30 ` Bryan Wu [this message]
2008-01-30 9:30 ` [PATCH 09/12] [Blackfin] serial driver: rework break flood anomaly handling to be more robust/realistic about what we can actually work around Bryan Wu
2008-01-30 9:30 ` [PATCH 10/12] [Blackfin] serial driver: use simpler comment headers and strip out information that is maintained in the scm's log Bryan Wu
2008-01-30 9:30 ` [PATCH 11/12] [Blackfin] serial driver: ADSP-BF52x arch/mach support Bryan Wu
2008-01-30 21:01 ` Mike Frysinger
2008-01-31 6:47 ` [PATCH 11/12 try #2] " Bryan Wu
2008-01-30 9:30 ` [PATCH 12/12] [Blackfin] serial driver: Fix bug Poll RTS/CTS status in DMA mode as well Bryan Wu
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=1201685412-29095-9-git-send-email-bryan.wu@analog.com \
--to=bryan.wu@analog.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=michael.frysinger@analog.com \
/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