Revert "serial: ns16550: Add RX interrupt buffer support"

This reverts commit 6822cf3ec7.

As Bin Meng has tested and pointed out, we don't need the RX interrupt
for the RX buffer support at all. Just reading all available characters
into a buffer is sufficient to solve the problem with the dropped
characters upon long lines pasted into the U-Boot prompt. Since this
RX buffer support can be implemented in a generic way, without any
device specifica (e.g. for the ns16550), I'll post a new patch with
a new serial RX buffer support for DM, which all DM based serial
drivers can use.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Simon Glass <sjg@chromium.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Tom Rini <trini@konsulko.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
Stefan Roese 2017-08-16 17:37:15 +02:00 committed by Bin Meng
parent 76e726502e
commit 7fded0ce0f
3 changed files with 5 additions and 138 deletions

View file

@ -64,16 +64,6 @@ config DM_SERIAL
implements serial_putc() etc. The uclass interface is implements serial_putc() etc. The uclass interface is
defined in include/serial.h. defined in include/serial.h.
config SERIAL_IRQ_BUFFER
bool "Enable RX interrupt buffer for serial input"
depends on DM_SERIAL
default n
help
Enable RX interrupt buffer support for the serial driver.
This enables pasting longer strings, even when the RX FIFO
of the UART is not big enough (e.g. 16 bytes on the normal
NS16550).
config SPL_DM_SERIAL config SPL_DM_SERIAL
bool "Enable Driver Model for serial drivers in SPL" bool "Enable Driver Model for serial drivers in SPL"
depends on DM_SERIAL depends on DM_SERIAL

View file

@ -314,80 +314,6 @@ DEBUG_UART_FUNCS
#endif #endif
#ifdef CONFIG_DM_SERIAL #ifdef CONFIG_DM_SERIAL
#if CONFIG_IS_ENABLED(SERIAL_IRQ_BUFFER)
#define BUF_COUNT 256
static void rx_fifo_to_buf(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
struct ns16550_platdata *plat = dev->platdata;
/* Read all available chars into buffer */
while ((serial_in(&com_port->lsr) & UART_LSR_DR)) {
plat->buf[plat->wr_ptr++] = serial_in(&com_port->rbr);
plat->wr_ptr %= BUF_COUNT;
}
}
static int rx_pending(struct udevice *dev)
{
struct ns16550_platdata *plat = dev->platdata;
/*
* At startup it may happen, that some already received chars are
* "stuck" in the RX FIFO, even with the interrupt enabled. This
* RX FIFO flushing makes sure, that these chars are read out and
* the RX interrupts works as expected.
*/
rx_fifo_to_buf(dev);
return plat->rd_ptr != plat->wr_ptr ? 1 : 0;
}
static int rx_get(struct udevice *dev)
{
struct ns16550_platdata *plat = dev->platdata;
char val;
val = plat->buf[plat->rd_ptr++];
plat->rd_ptr %= BUF_COUNT;
return val;
}
void ns16550_handle_irq(void *data)
{
struct udevice *dev = (struct udevice *)data;
struct NS16550 *const com_port = dev_get_priv(dev);
/* Check if interrupt is pending */
if (serial_in(&com_port->iir) & UART_IIR_NO_INT)
return;
/* Flush all available characters from the RX FIFO into the RX buffer */
rx_fifo_to_buf(dev);
}
#else /* CONFIG_SERIAL_IRQ_BUFFER */
static int rx_pending(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
return serial_in(&com_port->lsr) & UART_LSR_DR ? 1 : 0;
}
static int rx_get(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
return serial_in(&com_port->rbr);
}
#endif /* CONFIG_SERIAL_IRQ_BUFFER */
static int ns16550_serial_putc(struct udevice *dev, const char ch) static int ns16550_serial_putc(struct udevice *dev, const char ch)
{ {
struct NS16550 *const com_port = dev_get_priv(dev); struct NS16550 *const com_port = dev_get_priv(dev);
@ -413,17 +339,19 @@ static int ns16550_serial_pending(struct udevice *dev, bool input)
struct NS16550 *const com_port = dev_get_priv(dev); struct NS16550 *const com_port = dev_get_priv(dev);
if (input) if (input)
return rx_pending(dev); return serial_in(&com_port->lsr) & UART_LSR_DR ? 1 : 0;
else else
return serial_in(&com_port->lsr) & UART_LSR_THRE ? 0 : 1; return serial_in(&com_port->lsr) & UART_LSR_THRE ? 0 : 1;
} }
static int ns16550_serial_getc(struct udevice *dev) static int ns16550_serial_getc(struct udevice *dev)
{ {
if (!ns16550_serial_pending(dev, true)) struct NS16550 *const com_port = dev_get_priv(dev);
if (!(serial_in(&com_port->lsr) & UART_LSR_DR))
return -EAGAIN; return -EAGAIN;
return rx_get(dev); return serial_in(&com_port->rbr);
} }
static int ns16550_serial_setbrg(struct udevice *dev, int baudrate) static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
@ -446,40 +374,9 @@ int ns16550_serial_probe(struct udevice *dev)
com_port->plat = dev_get_platdata(dev); com_port->plat = dev_get_platdata(dev);
NS16550_init(com_port, -1); NS16550_init(com_port, -1);
#if CONFIG_IS_ENABLED(SERIAL_IRQ_BUFFER)
if (gd->flags & GD_FLG_RELOC) {
struct ns16550_platdata *plat = dev->platdata;
/* Allocate the RX buffer */
plat->buf = malloc(BUF_COUNT);
/* Install the interrupt handler */
irq_install_handler(plat->irq, ns16550_handle_irq, dev);
/* Enable RX interrupts */
serial_out(UART_IER_RDI, &com_port->ier);
}
#endif
return 0; return 0;
} }
#if CONFIG_IS_ENABLED(SERIAL_PRESENT) && \
(!defined(CONFIG_TPL_BUILD) || defined(CONFIG_TPL_DM_SERIAL))
static int ns16550_serial_remove(struct udevice *dev)
{
#if CONFIG_IS_ENABLED(SERIAL_IRQ_BUFFER)
if (gd->flags & GD_FLG_RELOC) {
struct ns16550_platdata *plat = dev->platdata;
irq_free_handler(plat->irq);
}
#endif
return 0;
}
#endif
#if CONFIG_IS_ENABLED(OF_CONTROL) #if CONFIG_IS_ENABLED(OF_CONTROL)
enum { enum {
PORT_NS16550 = 0, PORT_NS16550 = 0,
@ -561,15 +458,6 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
if (port_type == PORT_JZ4780) if (port_type == PORT_JZ4780)
plat->fcr |= UART_FCR_UME; plat->fcr |= UART_FCR_UME;
#if CONFIG_IS_ENABLED(SERIAL_IRQ_BUFFER)
plat->irq = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
"interrupts", 0);
if (!plat->irq) {
debug("ns16550 interrupt not provided\n");
return -EINVAL;
}
#endif
return 0; return 0;
} }
#endif #endif
@ -617,7 +505,6 @@ U_BOOT_DRIVER(ns16550_serial) = {
#endif #endif
.priv_auto_alloc_size = sizeof(struct NS16550), .priv_auto_alloc_size = sizeof(struct NS16550),
.probe = ns16550_serial_probe, .probe = ns16550_serial_probe,
.remove = ns16550_serial_remove,
.ops = &ns16550_serial_ops, .ops = &ns16550_serial_ops,
.flags = DM_FLAG_PRE_RELOC, .flags = DM_FLAG_PRE_RELOC,
}; };

View file

@ -51,10 +51,6 @@
* @base: Base register address * @base: Base register address
* @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...) * @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...)
* @clock: UART base clock speed in Hz * @clock: UART base clock speed in Hz
*
* @buf: Pointer to the RX interrupt buffer
* @rd_ptr: Read pointer in the RX interrupt buffer
* @wr_ptr: Write pointer in the RX interrupt buffer
*/ */
struct ns16550_platdata { struct ns16550_platdata {
unsigned long base; unsigned long base;
@ -62,12 +58,6 @@ struct ns16550_platdata {
int clock; int clock;
int reg_offset; int reg_offset;
u32 fcr; u32 fcr;
int irq;
char *buf;
int rd_ptr;
int wr_ptr;
}; };
struct udevice; struct udevice;