mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 00:52:01 +00:00
[Blackfin] serial driver: fix bug - cache the bits of the LSR on systems where the LSR is read-to-clear
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>
This commit is contained in:
parent
4c195ad88b
commit
0bcfd70ea1
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user