]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
drivers: serial: Add xtensa semihosting driver
authorJiaxun Yang <jiaxun.yang@flygoat.com>
Tue, 18 Jun 2024 13:56:06 +0000 (14:56 +0100)
committerTom Rini <trini@konsulko.com>
Thu, 4 Jul 2024 22:08:37 +0000 (16:08 -0600)
Add xtensa semihosting driver.

It can't use regular semihosting driver as Xtensa's has it's own
semihosting ABI.

Tested-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/serial_xtensa_semihosting.c [new file with mode: 0644]

index 1fe4607598eb92d55a3022d5e286c2b7bb1cf0ec..3a1e5a6f28776d1c783fc46b8b53fa9a0464804c 100644 (file)
@@ -501,6 +501,15 @@ config DEBUG_UART_MT7620
          driver will be available until the real driver model serial is
          running.
 
+config DEBUG_UART_XTENSA_SEMIHOSTING
+       bool "Xtensa semihosting"
+       depends on XTENSA_SEMIHOSTING_SERIAL
+       help
+         Select this to enable the debug UART using the Xtensa 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.
+
 endchoice
 
 config DEBUG_UART_BASE
@@ -936,7 +945,6 @@ config SH_SCIF_CLK_FREQ
 config SEMIHOSTING_SERIAL
        bool "Semihosting UART support"
        depends on SEMIHOSTING && !SERIAL_RX_BUFFER
-       imply SERIAL_PUTS
        help
          Select this to enable a serial UART using semihosting. Special halt
          instructions will be issued which an external debugger (such as a
@@ -1115,6 +1123,14 @@ config XEN_SERIAL
          If built without DM support, then requires Xen
          to be built with CONFIG_VERBOSE_DEBUG.
 
+config XTENSA_SEMIHOSTING_SERIAL
+       bool "Xtensa Semihosting UART support"
+       depends on DM_SERIAL
+       depends on XTENSA_SEMIHOSTING
+       imply SERIAL_PUTS
+       help
+         Select this to enable a serial UART using Xtensa semihosting.
+
 choice
        prompt "Console port"
        default 8xx_CONS_SMC1
index dbe598b74064805a1e451edc6df6bedc3eaea8c4..78810f98367c05e393b9bd38c64a6f9d9613213c 100644 (file)
@@ -60,6 +60,7 @@ obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o
 obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o
 obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
 obj-$(CONFIG_XEN_SERIAL) += serial_xen.o
+obj-$(CONFIG_XTENSA_SEMIHOSTING_SERIAL) += serial_xtensa_semihosting.o
 obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o
 
 ifndef CONFIG_SPL_BUILD
diff --git a/drivers/serial/serial_xtensa_semihosting.c b/drivers/serial/serial_xtensa_semihosting.c
new file mode 100644 (file)
index 0000000..0e59a9b
--- /dev/null
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ */
+
+#include <dm.h>
+#include <malloc.h>
+#include <serial.h>
+
+#include <asm/platform/simcall.h>
+
+/**
+ * struct simc_serial_priv - Semihosting serial private data
+ * @counter: Counter used to fake pending every other call
+ */
+struct simc_serial_priv {
+       unsigned int counter;
+};
+
+static int simc_serial_getc(struct udevice *dev)
+{
+       char ch = 0;
+
+       simc_read(0, &ch, sizeof(ch));
+
+       return ch;
+}
+
+static int simc_serial_putc(struct udevice *dev, const char ch)
+{
+       char str[2] = {0};
+
+       str[0] = ch;
+       simc_write(1, str, 1);
+
+       return 0;
+}
+
+static int simc_serial_pending(struct udevice *dev, bool input)
+{
+       struct simc_serial_priv *priv = dev_get_priv(dev);
+
+       if (input) {
+               int res = simc_poll(0);
+               return res < 0 ? priv->counter++ & 1 : res;
+       }
+
+       return false;
+}
+
+static ssize_t smh_serial_puts(struct udevice *dev, const char *s, size_t len)
+{
+       int ret;
+
+       ret = simc_write(1, s, len);
+
+       return ret;
+}
+
+static const struct dm_serial_ops simc_serial_ops = {
+       .putc = simc_serial_putc,
+       .puts = smh_serial_puts,
+       .getc = simc_serial_getc,
+       .pending = simc_serial_pending,
+};
+
+U_BOOT_DRIVER(simc_serial) = {
+       .name   = "serial_xtensa_semihosting",
+       .id     = UCLASS_SERIAL,
+       .priv_auto = sizeof(struct simc_serial_priv),
+       .ops    = &simc_serial_ops,
+       .flags  = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRVINFO(simc_serial) = {
+       .name = "serial_xtensa_semihosting",
+};
+
+#if CONFIG_IS_ENABLED(DEBUG_UART_XTENSA_SEMIHOSTING)
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int c)
+{
+       simc_serial_putc(NULL, c);
+}
+
+DEBUG_UART_FUNCS
+#endif