diff options
| author | Tom Rini <[email protected]> | 2022-04-02 15:28:43 -0400 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2022-04-02 15:28:43 -0400 |
| commit | 10d615f2fcc0d2ef1d611844eb6032fe0fca8afd (patch) | |
| tree | fc64ed7fef66e55214c75b98a90531645a203294 /drivers | |
| parent | 5b160c3a13f80708b4a720119cd2a1ef161e57f0 (diff) | |
| parent | 7a763471894feb58d5a1bdf78ea7014c7a952264 (diff) | |
Merge branch '2022-04-01-arm-semihosting-cleanups-and-new-features' into next
This brings in two related series. The first from Andre:
This series is the continuation of last year's effort to support the new
Armv8-R64 application profile. This led to a significant rework of the
existing fastmodel (FVP) support, to both upgrade it to newest U-Boot
standards (OF_CONTROL and distro_boot support), but also to generalise
the code, so that plugging in the v8-R64 support in the last patch gets
much easier. This is because apart from the twisted memory map between
the two profiles there is actually little difference, when it comes to
U-Boot relevant parts of the hardware.
I kept the legacy semihosting support (which picks up magic files from
the current directory), but if that fails, we go and try virtio-blk
(.iso installer images work), then virtio-net.
Please have a look, and give it a try, if possible. Both the v8-R and
v8-A FVP models are available for free on the Arm website[1].
Patch 01/11 fixes a regression introduced in December, it should be
applied now. The rest of the patches are for the next merge window.
[1]
https://developer.arm.com/tools-and-software/simulation-models/fast-models
And the second from Sean (where we exclude 27, 28 and 29 for now):
This cleans up the semihosting code and adds the following new features:
- hostfs support (like sandbox)
- support for being used as a SPL boot device
- serial device support
- falling back to normal drivers if semihosting is disabled
The main device affected by these changes is vexpress64, so I'd
appreciate
if Andre (or anyone else) could try booting.
These changes are motivated by bringup for ls1046a. When forcing JTAG
boot, this device disables most communication peripherals, including
serial and ethernet devices. This appears to be fixed in later
generation devices, but we are stuck with it for now. Semihosting
provides an easy way to run a few console commands.
The patches in this series are organized as follows:
0-4: rST conversions and other documentation updates
5-9: Semihosting cleanups
10-14: Filesystem support (including SPL boot device)
15-16: Serial support
16: Documentation update
17: JTAG boot support for LS1046A
19-25: Semihosting fallback
26-29: DM puts support
The last two groups of patches are "bonus;" the first 17 patches stand
on their own. The last two groups could be broken out as separate
series, but I have kept them in this one to help with my sanity (and not
have to deal with too many outstanding series).
Patch 14 depends on [1] to apply cleanly. Patch 17 depends on [2] for
correctness. This series should be applied to u-boot/next (in
particular, the EROFS series must have been applied).
[1]
https://lore.kernel.org/u-boot/CACRpkdZ+9fmNjC_mvrbPa9-iuTQVd8UkJ7Zpe7cL0c5vZygsVw@mail.gmail.com/T/
[2]
https://lore.kernel.org/u-boot/[email protected]/
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/serial/Kconfig | 35 | ||||
| -rw-r--r-- | drivers/serial/Makefile | 1 | ||||
| -rw-r--r-- | drivers/serial/serial-uclass.c | 26 | ||||
| -rw-r--r-- | drivers/serial/serial.c | 2 | ||||
| -rw-r--r-- | drivers/serial/serial_semihosting.c | 156 |
5 files changed, 218 insertions, 2 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 610f8062c76..76171e7146a 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 @@ -399,6 +412,15 @@ config DEBUG_UART_SANDBOX start up driver model. The driver will be available until the real driver model serial is running. +config DEBUG_UART_SEMIHOSTING + bool "semihosting" + depends on SEMIHOSTING_SERIAL + help + Select this to enable the debug UART using the semihosting driver. + This provides basic serial output from the console without needing to + start up driver model. The driver will be available until the real + driver model serial is running. + config DEBUG_UART_SIFIVE bool "SiFive UART" depends on SIFIVE_SERIAL @@ -782,6 +804,19 @@ config SCIF_CONSOLE on systems with RCar or SH SoCs, say Y to this option. If unsure, say N. +config SEMIHOSTING_SERIAL + bool "Semihosting UART support" + depends on SEMIHOSTING && !SERIAL_RX_BUFFER + help + Select this to enable a serial UART using semihosting. Special halt + instructions will be issued which an external debugger (such as a + JTAG emulator) may interpret. The debugger will display U-Boot's + console output on the host system. + + Enable this option only if you are using a debugger which supports + semihosting. If you are not using a debugger, this driver will halt + the boot. + config UNIPHIER_SERIAL bool "Support for UniPhier on-chip UART" depends on ARCH_UNIPHIER diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 52e70aa1917..b68b5e7b2bf 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -52,6 +52,7 @@ endif obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o +obj-$(CONFIG_SEMIHOSTING_SERIAL) += serial_semihosting.o obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index f30f352bd7a..10d6b800e2f 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) diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index ebbd21916d7..6cdbb89841c 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -126,6 +126,7 @@ serial_initfunc(mxc_serial_initialize); serial_initfunc(ns16550_serial_initialize); serial_initfunc(pl01x_serial_initialize); serial_initfunc(pxa_serial_initialize); +serial_initfunc(smh_serial_initialize); serial_initfunc(sh_serial_initialize); serial_initfunc(mtk_serial_initialize); @@ -180,6 +181,7 @@ int serial_initialize(void) ns16550_serial_initialize(); pl01x_serial_initialize(); pxa_serial_initialize(); + smh_serial_initialize(); sh_serial_initialize(); mtk_serial_initialize(); diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c new file mode 100644 index 00000000000..62b1b2241b3 --- /dev/null +++ b/drivers/serial/serial_semihosting.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Sean Anderson <[email protected]> + */ + +#include <common.h> +#include <dm.h> +#include <serial.h> +#include <semihosting.h> + +/** + * struct smh_serial_priv - Semihosting serial private data + * @infd: stdin file descriptor (or error) + */ +struct smh_serial_priv { + int infd; + int outfd; +}; + +#if CONFIG_IS_ENABLED(DM_SERIAL) +static int smh_serial_getc(struct udevice *dev) +{ + char ch = 0; + struct smh_serial_priv *priv = dev_get_priv(dev); + + if (priv->infd < 0) + return smh_getc(); + + smh_read(priv->infd, &ch, sizeof(ch)); + return ch; +} + +static int smh_serial_putc(struct udevice *dev, const char ch) +{ + smh_putc(ch); + return 0; +} + +static const struct dm_serial_ops smh_serial_ops = { + .putc = smh_serial_putc, + .getc = smh_serial_getc, +}; + +static int smh_serial_bind(struct udevice *dev) +{ + if (semihosting_enabled()) + return 0; + return -ENOENT; +} + +static int smh_serial_probe(struct udevice *dev) +{ + struct smh_serial_priv *priv = dev_get_priv(dev); + + priv->infd = smh_open(":tt", MODE_READ); + return 0; +} + +U_BOOT_DRIVER(smh_serial) = { + .name = "serial_semihosting", + .id = UCLASS_SERIAL, + .bind = smh_serial_bind, + .probe = smh_serial_probe, + .priv_auto = sizeof(struct smh_serial_priv), + .ops = &smh_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRVINFO(smh_serial) = { + .name = "serial_semihosting", +}; +#else /* DM_SERIAL */ +static int infd = -ENODEV; +static int outfd = -ENODEV; + +static int smh_serial_start(void) +{ + infd = smh_open(":tt", MODE_READ); + outfd = smh_open(":tt", MODE_WRITE); + return 0; +} + +static int smh_serial_stop(void) +{ + if (outfd >= 0) + smh_close(outfd); + return 0; +} + +static void smh_serial_setbrg(void) +{ +} + +static int smh_serial_getc(void) +{ + char ch = 0; + + if (infd < 0) + return smh_getc(); + + smh_read(infd, &ch, sizeof(ch)); + return ch; +} + +static int smh_serial_tstc(void) +{ + return 1; +} + +static void smh_serial_puts(const char *s) +{ + ulong unused; + + if (outfd < 0) + smh_puts(s); + else + smh_write(outfd, s, strlen(s), &unused); +} + +struct serial_device serial_smh_device = { + .name = "serial_smh", + .start = smh_serial_start, + .stop = smh_serial_stop, + .setbrg = smh_serial_setbrg, + .getc = smh_serial_getc, + .tstc = smh_serial_tstc, + .putc = smh_putc, + .puts = smh_serial_puts, +}; + +void smh_serial_initialize(void) +{ + if (semihosting_enabled()) + serial_register(&serial_smh_device); +} + +__weak struct serial_device *default_serial_console(void) +{ + return &serial_smh_device; +} +#endif + +#ifdef CONFIG_DEBUG_UART_SEMIHOSTING +#include <debug_uart.h> + +static inline void _debug_uart_init(void) +{ +} + +static inline void _debug_uart_putc(int c) +{ + smh_putc(c); +} + +DEBUG_UART_FUNCS +#endif |
