Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1d4b10c authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Paul Mundt
Browse files

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: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 75b93489
Loading
Loading
Loading
Loading
+34 −8
Original line number Diff line number Diff line
@@ -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;
+23 −6
Original line number Diff line number Diff line
@@ -322,7 +322,7 @@
#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);					\
@@ -330,7 +330,7 @@
  }									\
  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);				\
@@ -384,8 +384,12 @@
      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
@@ -422,8 +426,7 @@
    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)