Skip to content

Commit

Permalink
serial: sh-sci: FIFO sizing helper consolidation.
Browse files Browse the repository at this point in the history
This consolidates all of the TX/RX fill/room nonsense in to a single set
of fairly heavyweight definitions. The implementation goes in descending
order of complexity, testing the register map for capabilities until we
run out of options and do it the legacy SCI way. Masks are derived
directly from the per-port FIFO size, meaning that platforms with FIFO
sizes not matching the standard port types will still need to manually
fix them up.

This also fixes up a number of issues such as tx_empty being completely
bogus for SCI and IrDA ports, some ports using masks smaller or greater
than their FIFO size, and so forth.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
Paul Mundt committed Jun 14, 2011
1 parent 61a6976 commit 72b294c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 122 deletions.
126 changes: 24 additions & 102 deletions drivers/tty/serial/sh-sci.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
},
};

#define sci_getreg(up, offset) (sci_regmap[to_sci_port(up)->cfg->regtype] + offset)

/*
* The "offset" here is rather misleading, in that it refers to an enum
* value relative to the port mapping rather than the fixed offset
Expand All @@ -305,8 +307,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
*/
static unsigned int sci_serial_in(struct uart_port *p, int offset)
{
struct sci_port *s = to_sci_port(p);
struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + offset;
struct plat_sci_reg *reg = sci_getreg(p, offset);

if (reg->size == 8)
return ioread8(p->membase + (reg->offset << p->regshift));
Expand All @@ -320,8 +321,7 @@ static unsigned int sci_serial_in(struct uart_port *p, int offset)

static void sci_serial_out(struct uart_port *p, int offset, int value)
{
struct sci_port *s = to_sci_port(p);
struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + offset;
struct plat_sci_reg *reg = sci_getreg(p, offset);

if (reg->size == 8)
iowrite8(value, p->membase + (reg->offset << p->regshift));
Expand Down Expand Up @@ -433,108 +433,38 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */
}

#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785) || \
defined(CONFIG_CPU_SUBTYPE_SH7786)
static int scif_txfill(struct uart_port *port)
{
return sci_in(port, SCTFDR) & 0xff;
}

static int scif_txroom(struct uart_port *port)
static int sci_txfill(struct uart_port *port)
{
return SCIF_TXROOM_MAX - scif_txfill(port);
}
struct plat_sci_reg *reg;

static int scif_rxfill(struct uart_port *port)
{
return sci_in(port, SCRFDR) & 0xff;
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
static int scif_txfill(struct uart_port *port)
{
if (port->mapbase == 0xffe00000 ||
port->mapbase == 0xffe08000)
/* SCIF0/1*/
reg = sci_getreg(port, SCTFDR);
if (reg->size)
return sci_in(port, SCTFDR) & 0xff;
else
/* SCIF2 */
return sci_in(port, SCFDR) >> 8;
}

static int scif_txroom(struct uart_port *port)
{
if (port->mapbase == 0xffe00000 ||
port->mapbase == 0xffe08000)
/* SCIF0/1*/
return SCIF_TXROOM_MAX - scif_txfill(port);
else
/* SCIF2 */
return SCIF2_TXROOM_MAX - scif_txfill(port);
}

static int scif_rxfill(struct uart_port *port)
{
if ((port->mapbase == 0xffe00000) ||
(port->mapbase == 0xffe08000)) {
/* SCIF0/1*/
return sci_in(port, SCRFDR) & 0xff;
} else {
/* SCIF2 */
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)
reg = sci_getreg(port, SCFDR);
if (reg->size)
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)
{
return sci_in(port, SCFDR) >> 8;
}

static int scif_txroom(struct uart_port *port)
{
return SCIF_TXROOM_MAX - scif_txfill(port);
}

static int scif_rxfill(struct uart_port *port)
{
return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
}
#endif

static int sci_txfill(struct uart_port *port)
{
return !(sci_in(port, SCxSR) & SCI_TDRE);
}

static int sci_txroom(struct uart_port *port)
{
return !sci_txfill(port);
return port->fifosize - sci_txfill(port);
}

static int sci_rxfill(struct uart_port *port)
{
struct plat_sci_reg *reg;

reg = sci_getreg(port, SCRFDR);
if (reg->size)
return sci_in(port, SCRFDR) & 0xff;

reg = sci_getreg(port, SCFDR);
if (reg->size)
return sci_in(port, SCFDR) & ((port->fifosize << 1) - 1);

return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
}

Expand Down Expand Up @@ -574,10 +504,7 @@ static void sci_transmit_chars(struct uart_port *port)
return;
}

if (port->type == PORT_SCI)
count = sci_txroom(port);
else
count = scif_txroom(port);
count = sci_txroom(port);

do {
unsigned char c;
Expand Down Expand Up @@ -632,13 +559,8 @@ static void sci_receive_chars(struct uart_port *port)
return;

while (1) {
if (port->type == PORT_SCI)
count = sci_rxfill(port);
else
count = scif_rxfill(port);

/* Don't copy more bytes than there is room for in the buffer */
count = tty_buffer_request_room(tty, count);
count = tty_buffer_request_room(tty, sci_rxfill(port));

/* If for any reason we can't copy more data, we're done! */
if (count == 0)
Expand Down Expand Up @@ -1096,7 +1018,7 @@ static void sci_free_irq(struct sci_port *port)
static unsigned int sci_tx_empty(struct uart_port *port)
{
unsigned short status = sci_in(port, SCxSR);
unsigned short in_tx_fifo = scif_txfill(port);
unsigned short in_tx_fifo = sci_txfill(port);

return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
}
Expand Down
20 changes: 0 additions & 20 deletions drivers/tty/serial/sh-sci.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,6 @@
#include <linux/io.h>
#include <linux/gpio.h>

#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721) || \
defined(CONFIG_ARCH_SH73A0) || \
defined(CONFIG_ARCH_SH7367) || \
defined(CONFIG_ARCH_SH7377) || \
defined(CONFIG_ARCH_SH7372)
# define SCIF_RFDC_MASK 0x007f
# define SCIF_TXROOM_MAX 64
#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
# define SCIF_RFDC_MASK 0x007f
# define SCIF_TXROOM_MAX 64
/* SH7763 SCIF2 support */
# define SCIF2_RFDC_MASK 0x001f
# define SCIF2_TXROOM_MAX 16
#else
# define SCIF_RFDC_MASK 0x001f
# define SCIF_TXROOM_MAX 16
#endif

#define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND)
#define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF)
#define SCxSR_TDxE(port) (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE)
Expand Down

0 comments on commit 72b294c

Please sign in to comment.