serial: serial-uclass: Add generic serial RX buffer support
Pasting longer lines into the U-Boot console prompt sometimes leads to characters missing. One problem here is the small 16-byte FIFO of the legacy NS16550 UART, e.g. on x86 platforms. This patch now introduces a Kconfig option to enable RX buffer support for all DM based serial drivers. With this option enabled, I was able paste really long lines into the U-Boot console, without any characters missing. 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> Tested-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
7fded0ce0f
commit
3ca7a06afb
@ -64,6 +64,21 @@ config DM_SERIAL
|
||||
implements serial_putc() etc. The uclass interface is
|
||||
defined in include/serial.h.
|
||||
|
||||
config SERIAL_RX_BUFFER
|
||||
bool "Enable RX buffer for serial input"
|
||||
depends on DM_SERIAL
|
||||
help
|
||||
Enable RX 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 SERIAL_RX_BUFFER_SIZE
|
||||
int "RX buffer size"
|
||||
depends on SERIAL_RX_BUFFER
|
||||
default 256
|
||||
help
|
||||
The size of the RX buffer (needs to be power of 2)
|
||||
|
||||
config SPL_DM_SERIAL
|
||||
bool "Enable Driver Model for serial drivers in SPL"
|
||||
depends on DM_SERIAL
|
||||
|
@ -160,7 +160,7 @@ static void _serial_puts(struct udevice *dev, const char *str)
|
||||
_serial_putc(dev, *str++);
|
||||
}
|
||||
|
||||
static int _serial_getc(struct udevice *dev)
|
||||
static int __serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct dm_serial_ops *ops = serial_get_ops(dev);
|
||||
int err;
|
||||
@ -174,7 +174,7 @@ static int _serial_getc(struct udevice *dev)
|
||||
return err >= 0 ? err : 0;
|
||||
}
|
||||
|
||||
static int _serial_tstc(struct udevice *dev)
|
||||
static int __serial_tstc(struct udevice *dev)
|
||||
{
|
||||
struct dm_serial_ops *ops = serial_get_ops(dev);
|
||||
|
||||
@ -184,6 +184,44 @@ static int _serial_tstc(struct udevice *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
|
||||
static int _serial_tstc(struct udevice *dev)
|
||||
{
|
||||
struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
|
||||
|
||||
/* Read all available chars into the RX buffer */
|
||||
while (__serial_tstc(dev)) {
|
||||
upriv->buf[upriv->wr_ptr++] = __serial_getc(dev);
|
||||
upriv->wr_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
return upriv->rd_ptr != upriv->wr_ptr ? 1 : 0;
|
||||
}
|
||||
|
||||
static int _serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
|
||||
char val;
|
||||
|
||||
val = upriv->buf[upriv->rd_ptr++];
|
||||
upriv->rd_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#else /* CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) */
|
||||
|
||||
static int _serial_getc(struct udevice *dev)
|
||||
{
|
||||
return __serial_getc(dev);
|
||||
}
|
||||
|
||||
static int _serial_tstc(struct udevice *dev)
|
||||
{
|
||||
return __serial_tstc(dev);
|
||||
}
|
||||
#endif /* CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) */
|
||||
|
||||
void serial_putc(char ch)
|
||||
{
|
||||
if (gd->cur_serial_dev)
|
||||
@ -359,6 +397,12 @@ static int serial_post_probe(struct udevice *dev)
|
||||
sdev.puts = serial_stub_puts;
|
||||
sdev.getc = serial_stub_getc;
|
||||
sdev.tstc = serial_stub_tstc;
|
||||
|
||||
#if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
|
||||
/* Allocate the RX buffer */
|
||||
upriv->buf = malloc(CONFIG_SERIAL_RX_BUFFER_SIZE);
|
||||
#endif
|
||||
|
||||
stdio_register_dev(&sdev, &upriv->sdev);
|
||||
#endif
|
||||
return 0;
|
||||
|
@ -148,10 +148,18 @@ struct dm_serial_ops {
|
||||
/**
|
||||
* struct serial_dev_priv - information about a device used by the uclass
|
||||
*
|
||||
* @sdev: stdio device attached to this uart
|
||||
* @sdev: stdio device attached to this uart
|
||||
*
|
||||
* @buf: Pointer to the RX buffer
|
||||
* @rd_ptr: Read pointer in the RX buffer
|
||||
* @wr_ptr: Write pointer in the RX buffer
|
||||
*/
|
||||
struct serial_dev_priv {
|
||||
struct stdio_dev *sdev;
|
||||
|
||||
char *buf;
|
||||
int rd_ptr;
|
||||
int wr_ptr;
|
||||
};
|
||||
|
||||
/* Access the serial operations for a device */
|
||||
|
Loading…
Reference in New Issue
Block a user