From 1a22f08dbd0e77c7cf45b5f527f93131d0b591b6 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 11 Nov 2008 12:19:05 +0900 Subject: serial: sh-sci: fix cannot work SH7723 SCIFA SH7723 has SCIFA. This module is similer SCI register map, but it has FIFO. So this patch adds new type(PORT_SCIFA) and change some type checking. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 20 +++++++++++--------- drivers/serial/sh-sci.h | 16 ++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5c0f32c7fbf6..518c0321e4d3 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -478,10 +478,10 @@ static void sci_transmit_chars(struct uart_port *port) return; } - if (port->type == PORT_SCIF) - count = scif_txroom(port); - else + if (port->type == PORT_SCI) count = sci_txroom(port); + else + count = scif_txroom(port); do { unsigned char c; @@ -510,7 +510,7 @@ static void sci_transmit_chars(struct uart_port *port) } else { ctrl = sci_in(port, SCSCR); - if (port->type == PORT_SCIF) { + if (port->type != PORT_SCI) { sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); } @@ -536,10 +536,10 @@ static inline void sci_receive_chars(struct uart_port *port) return; while (1) { - if (port->type == PORT_SCIF) - count = scif_rxroom(port); - else + if (port->type == PORT_SCI) count = sci_rxroom(port); + else + count = scif_rxroom(port); /* Don't copy more bytes than there is room for in the buffer */ count = tty_buffer_request_room(tty, count); @@ -714,7 +714,7 @@ static inline int sci_handle_breaks(struct uart_port *port) #if defined(SCIF_ORER) /* XXX: Handle SCIF overrun error */ - if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { + if (port->type != PORT_SCI && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { sci_out(port, SCLSR, 0); if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) { copied++; @@ -1042,7 +1042,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ - if (port->type == PORT_SCIF) + if (port->type != PORT_SCI) sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); smr_val = sci_in(port, SCSMR) & 3; @@ -1085,6 +1085,7 @@ static const char *sci_type(struct uart_port *port) case PORT_SCI: return "sci"; case PORT_SCIF: return "scif"; case PORT_IRDA: return "irda"; + case PORT_SCIFA: return "scifa"; } return NULL; @@ -1112,6 +1113,7 @@ static void sci_config_port(struct uart_port *port, int flags) s->init_pins = sci_init_pins_sci; break; case PORT_SCIF: + case PORT_SCIFA: s->init_pins = sci_init_pins_scif; break; case PORT_IRDA: diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 6163a45f968f..9f33b064172e 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -289,18 +289,18 @@ #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ static inline unsigned int sci_##name##_in(struct uart_port *port) \ { \ - if (port->type == PORT_SCI) { \ - SCI_IN(sci_size, sci_offset) \ - } else { \ - SCI_IN(scif_size, scif_offset); \ + if (port->type == PORT_SCIF) { \ + SCI_IN(scif_size, scif_offset) \ + } else { /* PORT_SCI or PORT_SCIFA */ \ + SCI_IN(sci_size, sci_offset); \ } \ } \ static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ { \ - if (port->type == PORT_SCI) { \ - SCI_OUT(sci_size, sci_offset, value) \ - } else { \ - SCI_OUT(scif_size, scif_offset, value); \ + if (port->type == PORT_SCIF) { \ + SCI_OUT(scif_size, scif_offset, value) \ + } else { /* PORT_SCI or PORT_SCIFA */ \ + SCI_OUT(sci_size, sci_offset, value); \ } \ } -- cgit v1.2.2 From 272966c070237c8cb540fe67e06df51bc6ea9cc2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 13 Nov 2008 17:46:06 +0900 Subject: serial: sh-sci: Reorder the SCxTDR write after the TDxE clear. Under qemu there is a race between the TDxE read-and-clear and the SCxTDR write. While on hardware it can be gauranteed that the read-and-clear will happen prior to the character being written out, no such assumption can be made under emulation. As this path happens with IRQs off and the hardware itself doesn't care about the ordering, move the SCxTDR write until after the read-and-clear. Signed-off-by: Vladimir Prus Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 518c0321e4d3..165fc010978c 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -144,9 +144,9 @@ static void put_char(struct uart_port *port, char c) status = sci_in(port, SCxSR); } while (!(status & SCxSR_TDxE(port))); - sci_out(port, SCxTDR, c); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + sci_out(port, SCxTDR, c); spin_unlock_irqrestore(&port->lock, flags); } -- cgit v1.2.2