提交 d1d4b10c 编写于 作者: G Guennadi Liakhovetski 提交者: Paul Mundt

serial: sh-sci: fix handling of SCIFB sh-mobile ports

SCIFB ports have a slightly different register layout and a different FIFO
size from SCIFA ports, in DMA mode they have to be treated just like SCIFA.
Signed-off-by: NGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: NPaul Mundt <lethal@linux-sh.org>
上级 75b93489
...@@ -346,6 +346,27 @@ static int scif_rxfill(struct uart_port *port) ...@@ -346,6 +346,27 @@ static int scif_rxfill(struct uart_port *port)
return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
} }
} }
#elif defined(CONFIG_ARCH_SH7372)
static int scif_txfill(struct uart_port *port)
{
if (port->type == PORT_SCIFA)
return sci_in(port, SCFDR) >> 8;
else
return sci_in(port, SCTFDR);
}
static int scif_txroom(struct uart_port *port)
{
return port->fifosize - scif_txfill(port);
}
static int scif_rxfill(struct uart_port *port)
{
if (port->type == PORT_SCIFA)
return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
else
return sci_in(port, SCRFDR);
}
#else #else
static int scif_txfill(struct uart_port *port) static int scif_txfill(struct uart_port *port)
{ {
...@@ -683,7 +704,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) ...@@ -683,7 +704,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
u16 ssr = sci_in(port, SCxSR); u16 ssr = sci_in(port, SCxSR);
/* Disable future Rx interrupts */ /* Disable future Rx interrupts */
if (port->type == PORT_SCIFA) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
disable_irq_nosync(irq); disable_irq_nosync(irq);
scr |= 0x4000; scr |= 0x4000;
} else { } else {
...@@ -928,7 +949,7 @@ static void sci_dma_tx_complete(void *arg) ...@@ -928,7 +949,7 @@ static void sci_dma_tx_complete(void *arg)
if (!uart_circ_empty(xmit)) { if (!uart_circ_empty(xmit)) {
schedule_work(&s->work_tx); schedule_work(&s->work_tx);
} else if (port->type == PORT_SCIFA) { } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
u16 ctrl = sci_in(port, SCSCR); u16 ctrl = sci_in(port, SCSCR);
sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE);
} }
...@@ -1183,7 +1204,7 @@ static void sci_start_tx(struct uart_port *port) ...@@ -1183,7 +1204,7 @@ static void sci_start_tx(struct uart_port *port)
unsigned short ctrl; unsigned short ctrl;
#ifdef CONFIG_SERIAL_SH_SCI_DMA #ifdef CONFIG_SERIAL_SH_SCI_DMA
if (port->type == PORT_SCIFA) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
u16 new, scr = sci_in(port, SCSCR); u16 new, scr = sci_in(port, SCSCR);
if (s->chan_tx) if (s->chan_tx)
new = scr | 0x8000; new = scr | 0x8000;
...@@ -1196,7 +1217,7 @@ static void sci_start_tx(struct uart_port *port) ...@@ -1196,7 +1217,7 @@ static void sci_start_tx(struct uart_port *port)
s->cookie_tx < 0) s->cookie_tx < 0)
schedule_work(&s->work_tx); schedule_work(&s->work_tx);
#endif #endif
if (!s->chan_tx || port->type == PORT_SCIFA) { if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
ctrl = sci_in(port, SCSCR); ctrl = sci_in(port, SCSCR);
sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE);
...@@ -1209,7 +1230,7 @@ static void sci_stop_tx(struct uart_port *port) ...@@ -1209,7 +1230,7 @@ static void sci_stop_tx(struct uart_port *port)
/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
ctrl = sci_in(port, SCSCR); ctrl = sci_in(port, SCSCR);
if (port->type == PORT_SCIFA) if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x8000; ctrl &= ~0x8000;
ctrl &= ~SCI_CTRL_FLAGS_TIE; ctrl &= ~SCI_CTRL_FLAGS_TIE;
sci_out(port, SCSCR, ctrl); sci_out(port, SCSCR, ctrl);
...@@ -1221,7 +1242,7 @@ static void sci_start_rx(struct uart_port *port) ...@@ -1221,7 +1242,7 @@ static void sci_start_rx(struct uart_port *port)
/* Set RIE (Receive Interrupt Enable) bit in SCSCR */ /* Set RIE (Receive Interrupt Enable) bit in SCSCR */
ctrl |= sci_in(port, SCSCR); ctrl |= sci_in(port, SCSCR);
if (port->type == PORT_SCIFA) if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x4000; ctrl &= ~0x4000;
sci_out(port, SCSCR, ctrl); sci_out(port, SCSCR, ctrl);
} }
...@@ -1232,7 +1253,7 @@ static void sci_stop_rx(struct uart_port *port) ...@@ -1232,7 +1253,7 @@ static void sci_stop_rx(struct uart_port *port)
/* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
ctrl = sci_in(port, SCSCR); ctrl = sci_in(port, SCSCR);
if (port->type == PORT_SCIFA) if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x4000; ctrl &= ~0x4000;
ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
sci_out(port, SCSCR, ctrl); sci_out(port, SCSCR, ctrl);
...@@ -1270,7 +1291,7 @@ static void rx_timer_fn(unsigned long arg) ...@@ -1270,7 +1291,7 @@ static void rx_timer_fn(unsigned long arg)
struct uart_port *port = &s->port; struct uart_port *port = &s->port;
u16 scr = sci_in(port, SCSCR); u16 scr = sci_in(port, SCSCR);
if (port->type == PORT_SCIFA) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
scr &= ~0x4000; scr &= ~0x4000;
enable_irq(s->irqs[1]); enable_irq(s->irqs[1]);
} }
...@@ -1523,6 +1544,8 @@ static const char *sci_type(struct uart_port *port) ...@@ -1523,6 +1544,8 @@ static const char *sci_type(struct uart_port *port)
return "scif"; return "scif";
case PORT_SCIFA: case PORT_SCIFA:
return "scifa"; return "scifa";
case PORT_SCIFB:
return "scifb";
} }
return NULL; return NULL;
...@@ -1611,6 +1634,9 @@ static int __devinit sci_init_single(struct platform_device *dev, ...@@ -1611,6 +1634,9 @@ static int __devinit sci_init_single(struct platform_device *dev,
port->line = index; port->line = index;
switch (p->type) { switch (p->type) {
case PORT_SCIFB:
port->fifosize = 256;
break;
case PORT_SCIFA: case PORT_SCIFA:
port->fifosize = 64; port->fifosize = 64;
break; break;
......
...@@ -322,7 +322,7 @@ ...@@ -322,7 +322,7 @@
#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
static inline unsigned int sci_##name##_in(struct uart_port *port) \ static inline unsigned int sci_##name##_in(struct uart_port *port) \
{ \ { \
if (port->type == PORT_SCIF) { \ if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \
SCI_IN(scif_size, scif_offset) \ SCI_IN(scif_size, scif_offset) \
} else { /* PORT_SCI or PORT_SCIFA */ \ } else { /* PORT_SCI or PORT_SCIFA */ \
SCI_IN(sci_size, sci_offset); \ SCI_IN(sci_size, sci_offset); \
...@@ -330,7 +330,7 @@ ...@@ -330,7 +330,7 @@
} \ } \
static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
{ \ { \
if (port->type == PORT_SCIF) { \ if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \
SCI_OUT(scif_size, scif_offset, value) \ SCI_OUT(scif_size, scif_offset, value) \
} else { /* PORT_SCI or PORT_SCIFA */ \ } else { /* PORT_SCI or PORT_SCIFA */ \
SCI_OUT(sci_size, sci_offset, value); \ SCI_OUT(sci_size, sci_offset, value); \
...@@ -384,8 +384,12 @@ ...@@ -384,8 +384,12 @@
defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \
defined(CONFIG_ARCH_SH7367) || \ defined(CONFIG_ARCH_SH7367) || \
defined(CONFIG_ARCH_SH7377) || \ defined(CONFIG_ARCH_SH7377)
defined(CONFIG_ARCH_SH7372) #define SCIF_FNS(name, scif_offset, scif_size) \
CPU_SCIF_FNS(name, scif_offset, scif_size)
#elif defined(CONFIG_ARCH_SH7372)
#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \
CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size)
#define SCIF_FNS(name, scif_offset, scif_size) \ #define SCIF_FNS(name, scif_offset, scif_size) \
CPU_SCIF_FNS(name, scif_offset, scif_size) CPU_SCIF_FNS(name, scif_offset, scif_size)
#else #else
...@@ -422,8 +426,7 @@ ...@@ -422,8 +426,7 @@
defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \
defined(CONFIG_ARCH_SH7367) || \ defined(CONFIG_ARCH_SH7367) || \
defined(CONFIG_ARCH_SH7377) || \ defined(CONFIG_ARCH_SH7377)
defined(CONFIG_ARCH_SH7372)
SCIF_FNS(SCSMR, 0x00, 16) SCIF_FNS(SCSMR, 0x00, 16)
SCIF_FNS(SCBRR, 0x04, 8) SCIF_FNS(SCBRR, 0x04, 8)
...@@ -436,6 +439,20 @@ SCIF_FNS(SCFDR, 0x1c, 16) ...@@ -436,6 +439,20 @@ SCIF_FNS(SCFDR, 0x1c, 16)
SCIF_FNS(SCxTDR, 0x20, 8) SCIF_FNS(SCxTDR, 0x20, 8)
SCIF_FNS(SCxRDR, 0x24, 8) SCIF_FNS(SCxRDR, 0x24, 8)
SCIF_FNS(SCLSR, 0x00, 0) SCIF_FNS(SCLSR, 0x00, 0)
#elif defined(CONFIG_ARCH_SH7372)
SCIF_FNS(SCSMR, 0x00, 16)
SCIF_FNS(SCBRR, 0x04, 8)
SCIF_FNS(SCSCR, 0x08, 16)
SCIF_FNS(SCTDSR, 0x0c, 16)
SCIF_FNS(SCFER, 0x10, 16)
SCIF_FNS(SCxSR, 0x14, 16)
SCIF_FNS(SCFCR, 0x18, 16)
SCIF_FNS(SCFDR, 0x1c, 16)
SCIF_FNS(SCTFDR, 0x38, 16)
SCIF_FNS(SCRFDR, 0x3c, 16)
SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8)
SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8)
SCIF_FNS(SCLSR, 0x00, 0)
#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
defined(CONFIG_CPU_SUBTYPE_SH7724) defined(CONFIG_CPU_SUBTYPE_SH7724)
SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册