aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSean Anderson <sean.anderson@seco.com>2022-03-22 16:59:34 -0400
committerTom Rini <trini@konsulko.com>2022-04-01 16:56:54 -0400
commit7a763471894feb58d5a1bdf78ea7014c7a952264 (patch)
treefc64ed7fef66e55214c75b98a90531645a203294 /drivers
parent53b953f2ebad6263352cb1247618dc5b965863cc (diff)
downloadu-boot-7a763471894feb58d5a1bdf78ea7014c7a952264.zip
u-boot-7a763471894feb58d5a1bdf78ea7014c7a952264.tar.gz
u-boot-7a763471894feb58d5a1bdf78ea7014c7a952264.tar.bz2
serial: dm: Add support for puts
Some serial drivers can be vastly more efficient when printing multiple characters at once. Non-DM serial has had a puts option for these sorts of drivers; implement it for DM serial as well. Because we have to add carriage returns, we can't just pass the whole string directly to the serial driver. Instead, we print up to the newline, then print a carriage return, and then continue on. This is less efficient, but it is better than printing each character individually. It also avoids having to allocate memory just to add a few characters. Drivers may perform short writes (such as filling a FIFO) and return the number of characters written in len. We loop over them in the same way that _serial_putc loops over putc. This results in around sizeof(void *) growth for all boards with DM_SERIAL. The full implementation takes around 140 bytes. Signed-off-by: Sean Anderson <sean.anderson@seco.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/Kconfig13
-rw-r--r--drivers/serial/serial-uclass.c26
2 files changed, 37 insertions, 2 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index a07fab2..76171e7 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -133,6 +133,19 @@ config SERIAL_RX_BUFFER_SIZE
help
The size of the RX buffer (needs to be power of 2)
+config SERIAL_PUTS
+ bool "Enable printing strings all at once"
+ depends on DM_SERIAL
+ help
+ Some serial drivers are much more efficient when printing multiple
+ characters at once rather than printing characters individually. This
+ can be because they can load a fifo, or because individual print
+ calls have a constant overhead. With this option set, the serial
+ subsystem will try to provide serial drivers with as many characters
+ at once as possible, instead of printing characters one by one. Most
+ serial drivers do not need this config to print efficiently. If
+ unsure, say N.
+
config SERIAL_SEARCH_ALL
bool "Search for serial devices after default one failed"
depends on DM_SERIAL
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index f30f352..10d6b80 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -200,8 +200,30 @@ static void _serial_putc(struct udevice *dev, char ch)
static void _serial_puts(struct udevice *dev, const char *str)
{
- while (*str)
- _serial_putc(dev, *str++);
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+
+ if (!CONFIG_IS_ENABLED(SERIAL_PUTS) || !ops->puts) {
+ while (*str)
+ _serial_putc(dev, *str++);
+ return;
+ }
+
+ do {
+ const char *newline = strchrnul(str, '\n');
+ size_t len = newline - str + !!*newline;
+
+ do {
+ ssize_t written = ops->puts(dev, str, len);
+
+ if (written < 0)
+ return;
+ str += written;
+ len -= written;
+ } while (len);
+
+ if (*newline)
+ _serial_putc(dev, '\r');
+ } while (*str);
}
static int __serial_getc(struct udevice *dev)