Re: [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting

From: Jiaxun Yang
Date: Fri Oct 27 2023 - 16:49:13 EST




在2023年10月27日十月 下午7:26,Jiaxun Yang写道:
> UHI is MIPS's implementation of semihosting.
> Add an earlycon driver to help with debugging on boot.
>
> This driver is capable for print log using UHI's "Plog" or interact
> with KGDB using UHI's stdio function.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx>
> ---
> drivers/tty/serial/Kconfig | 13 ++++
> drivers/tty/serial/Makefile | 1 +
> drivers/tty/serial/earlycon-mips-uhi.c | 85 ++++++++++++++++++++++++++
> 3 files changed, 99 insertions(+)
> create mode 100644 drivers/tty/serial/earlycon-mips-uhi.c
>
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index bdc568a4ab66..04c62c6b45cd 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -85,6 +85,19 @@ config SERIAL_EARLYCON_SEMIHOST
> This is enabled with "earlycon=smh" on the kernel command line.
> The console is enabled when early_param is processed.
>
> +config SERIAL_EARLYCON_UHI

^ Oops there is a symbol name mismatch, will fix in v2.

Sorry for the noise.

Thanks
- Jiaxun

> + bool "Early console using MIPS UHI semihosting"
> + depends on MIPS
> + select SERIAL_CORE
> + select SERIAL_CORE_CONSOLE
> + select SERIAL_EARLYCON
> + help
> + Support for early debug console using UHI semihosting.
> + This enables the console before standard serial driver is probed.
> + This is enabled with "earlycon=uhi" or "earlycon=uhi_stdio" on the
> + kernel command line.
> + The console is enabled when early_param is processed.
> +
> config SERIAL_EARLYCON_RISCV_SBI
> bool "Early console using RISC-V SBI"
> depends on RISCV_SBI_V01
> diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> index f6b8c220dcfb..ef5e9c87aea1 100644
> --- a/drivers/tty/serial/Makefile
> +++ b/drivers/tty/serial/Makefile
> @@ -9,6 +9,7 @@ serial_base-y := serial_core.o serial_base_bus.o
> serial_ctrl.o serial_port.o
> obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
> obj-$(CONFIG_SERIAL_EARLYCON_SEMIHOST) += earlycon-semihost.o
> obj-$(CONFIG_SERIAL_EARLYCON_RISCV_SBI) += earlycon-riscv-sbi.o
> +obj-$(CONFIG_SERIAL_EARLYCON_MIPS_UHI) += earlycon-mips-uhi.o
>
> # These Sparc drivers have to appear before others such as 8250
> # which share ttySx minor node space. Otherwise console device
> diff --git a/drivers/tty/serial/earlycon-mips-uhi.c
> b/drivers/tty/serial/earlycon-mips-uhi.c
> new file mode 100644
> index 000000000000..002bb2c37064
> --- /dev/null
> +++ b/drivers/tty/serial/earlycon-mips-uhi.c
> @@ -0,0 +1,85 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MIPS UHI semihosting based earlycon
> + *
> + * Copyright (C) 2023 Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/console.h>
> +#include <linux/init.h>
> +#include <linux/serial_core.h>
> +#include <asm/uhi.h>
> +
> +static int stdin_fd = -1;
> +static int stdout_fd = -1;
> +
> +static void uhi_plog_write(struct console *con, const char *s,
> unsigned int n)
> +{
> + uhi_plog(s, 0);
> +}
> +
> +static void uhi_stdout_write(struct console *con, const char *s,
> unsigned int n)
> +{
> + if (stdout_fd < 0)
> + return;
> +
> + uhi_write(stdout_fd, s, n);
> +}
> +
> +#ifdef CONFIG_CONSOLE_POLL
> +static int uhi_stdin_read(struct console *con, char *s, unsigned int n)
> +{
> + if (stdin_fd < 0)
> + return 0;
> +
> + return uhi_read(stdin_fd, s, n);
> +}
> +#endif
> +
> +static int uhi_stdio_fd_open(struct console *co, char *options)
> +{
> + /*
> + * You have to open both stdin and stdout to get console work
> + * properly on some old CodeScape debugger.
> + */
> + stdin_fd = uhi_open("/dev/stdin", UHI_O_RDONLY, 0);
> + stdout_fd = uhi_open("/dev/stdout", UHI_O_WRONLY, 0);
> +
> + return (stdin_fd < 0 || stdout_fd < 0) ? -ENODEV : 0;
> +}
> +
> +static int uhi_stdio_fd_close(struct console *co)
> +{
> + int ret1 = 0, ret2 = 0;
> +
> + if (stdin_fd >= 0)
> + ret1 = uhi_close(stdin_fd);
> + if (stdout_fd >= 0)
> + ret2 = uhi_close(stdout_fd);
> +
> + return (ret1 < 0 || ret2 < 0) ? -ENODEV : 0;
> +}
> +
> +static int
> +__init early_uhi_setup(struct earlycon_device *device, const char *opt)
> +{
> + device->con->write = uhi_plog_write;
> + return 0;
> +}
> +
> +static int
> +__init early_uhi_stdio_setup(struct earlycon_device *device, const
> char *opt)
> +{
> +
> + device->con->setup = uhi_stdio_fd_open;
> + device->con->exit = uhi_stdio_fd_close;
> + device->con->write = uhi_stdout_write;
> +#ifdef CONFIG_CONSOLE_POLL
> + device->con->read = uhi_stdin_read;
> +#endif
> + return 0;
> +}
> +
> +EARLYCON_DECLARE(uhi, early_uhi_setup);
> +EARLYCON_DECLARE(uhi_stdio, early_uhi_stdio_setup);
> --
> 2.34.1

--
- Jiaxun