]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
serial: sh-sci: fix handling of SCIFB sh-mobile ports
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Sun, 23 May 2010 16:39:09 +0000 (16:39 +0000)
committerPaul Mundt <lethal@linux-sh.org>
Sun, 23 May 2010 23:53:37 +0000 (08:53 +0900)
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: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h

index 4f73fb756745cc19a2ddce3f62302369579aa1df..aaef223df67605a88be43c136baf99bb5739818e 100644 (file)
@@ -346,6 +346,27 @@ static int scif_rxfill(struct uart_port *port)
                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
 static int scif_txfill(struct uart_port *port)
 {
@@ -683,7 +704,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
                u16 ssr = sci_in(port, SCxSR);
 
                /* Disable future Rx interrupts */
-               if (port->type == PORT_SCIFA) {
+               if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
                        disable_irq_nosync(irq);
                        scr |= 0x4000;
                } else {
@@ -928,7 +949,7 @@ static void sci_dma_tx_complete(void *arg)
 
        if (!uart_circ_empty(xmit)) {
                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);
                sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE);
        }
@@ -1183,7 +1204,7 @@ static void sci_start_tx(struct uart_port *port)
        unsigned short ctrl;
 
 #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);
                if (s->chan_tx)
                        new = scr | 0x8000;
@@ -1196,7 +1217,7 @@ static void sci_start_tx(struct uart_port *port)
            s->cookie_tx < 0)
                schedule_work(&s->work_tx);
 #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 */
                ctrl = sci_in(port, SCSCR);
                sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE);
@@ -1209,7 +1230,7 @@ static void sci_stop_tx(struct uart_port *port)
 
        /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
        ctrl = sci_in(port, SCSCR);
-       if (port->type == PORT_SCIFA)
+       if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~0x8000;
        ctrl &= ~SCI_CTRL_FLAGS_TIE;
        sci_out(port, SCSCR, ctrl);
@@ -1221,7 +1242,7 @@ static void sci_start_rx(struct uart_port *port)
 
        /* Set RIE (Receive Interrupt Enable) bit in SCSCR */
        ctrl |= sci_in(port, SCSCR);
-       if (port->type == PORT_SCIFA)
+       if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~0x4000;
        sci_out(port, SCSCR, ctrl);
 }
@@ -1232,7 +1253,7 @@ static void sci_stop_rx(struct uart_port *port)
 
        /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
        ctrl = sci_in(port, SCSCR);
-       if (port->type == PORT_SCIFA)
+       if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~0x4000;
        ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
        sci_out(port, SCSCR, ctrl);
@@ -1270,7 +1291,7 @@ static void rx_timer_fn(unsigned long arg)
        struct uart_port *port = &s->port;
        u16 scr = sci_in(port, SCSCR);
 
-       if (port->type == PORT_SCIFA) {
+       if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
                scr &= ~0x4000;
                enable_irq(s->irqs[1]);
        }
@@ -1523,6 +1544,8 @@ static const char *sci_type(struct uart_port *port)
                return "scif";
        case PORT_SCIFA:
                return "scifa";
+       case PORT_SCIFB:
+               return "scifb";
        }
 
        return NULL;
@@ -1611,6 +1634,9 @@ static int __devinit sci_init_single(struct platform_device *dev,
        port->line      = index;
 
        switch (p->type) {
+       case PORT_SCIFB:
+               port->fifosize = 256;
+               break;
        case PORT_SCIFA:
                port->fifosize = 64;
                break;
index f70c49f915fa11c7878747f58973bebc899f5542..9b52f77a93057af3aa7ba8e69d002190f1b4aaab 100644 (file)
 #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_SCIF) {                                     \
+    if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {         \
       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_SCIF) {                                     \
+    if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {         \
       SCI_OUT(scif_size, scif_offset, value)                           \
     } else {   /* PORT_SCI or PORT_SCIFA */                            \
       SCI_OUT(sci_size, sci_offset, value);                            \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
       defined(CONFIG_CPU_SUBTYPE_SH7721) || \
       defined(CONFIG_ARCH_SH7367) || \
-      defined(CONFIG_ARCH_SH7377) || \
-      defined(CONFIG_ARCH_SH7372)
+      defined(CONFIG_ARCH_SH7377)
+#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) \
   CPU_SCIF_FNS(name, scif_offset, scif_size)
 #else
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
     defined(CONFIG_ARCH_SH7367) || \
-    defined(CONFIG_ARCH_SH7377) || \
-    defined(CONFIG_ARCH_SH7372)
+    defined(CONFIG_ARCH_SH7377)
 
 SCIF_FNS(SCSMR,  0x00, 16)
 SCIF_FNS(SCBRR,  0x04,  8)
@@ -436,6 +439,20 @@ SCIF_FNS(SCFDR,  0x1c, 16)
 SCIF_FNS(SCxTDR, 0x20,  8)
 SCIF_FNS(SCxRDR, 0x24,  8)
 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) ||\
       defined(CONFIG_CPU_SUBTYPE_SH7724)
 SCIx_FNS(SCSMR,  0x00, 16, 0x00, 16)