From 5953062ce13c4b07190d455d2aae228cd3756d42 Mon Sep 17 00:00:00 2001 From: Marcelo Politzer Date: Thu, 16 Sep 2021 14:29:51 -0300 Subject: [PATCH 1/2] serial: implement SBI UART support --- arch/riscv/lib/sbi.c | 11 ++++++ drivers/serial/Kconfig | 7 ++++ drivers/serial/Makefile | 1 + drivers/serial/serial_sbi.c | 77 +++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 drivers/serial/serial_sbi.c diff --git a/arch/riscv/lib/sbi.c b/arch/riscv/lib/sbi.c index 45a04fb82..209069c98 100644 --- a/arch/riscv/lib/sbi.c +++ b/arch/riscv/lib/sbi.c @@ -64,3 +64,14 @@ static int sbi_init(void) } core_initcall(sbi_init); + + +void sbi_console_putchar(int ch) +{ + sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch, 0, 0, 0, 0, 0); +} + +int sbi_console_getchar(void) +{ + return sbi_ecall(SBI_EXT_0_1_CONSOLE_GETCHAR, 0, 0, 0, 0, 0, 0, 0).error; +} diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b9750d177..002871445 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -173,4 +173,11 @@ config SERIAL_SIFIVE contains a SiFive UART IP block. This type of UART is present on SiFive FU540 SoCs, among others. +config SERIAL_SBI + tristate "RISCV SBI UART support" + depends on OFDEVICE + help + Select this option if you are building barebox for a RISCV with SBI + version 0.1.0 (legacy mode) implemented + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 5120b1737..b1de436ed 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_DRIVER_SERIAL_DIGIC) += serial_digic.o obj-$(CONFIG_DRIVER_SERIAL_LPUART) += serial_lpuart.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o obj-$(CONFIG_SERIAL_SIFIVE) += serial_sifive.o +obj-$(CONFIG_SERIAL_SBI) += serial_sbi.o diff --git a/drivers/serial/serial_sbi.c b/drivers/serial/serial_sbi.c new file mode 100644 index 000000000..a7e57885f --- /dev/null +++ b/drivers/serial/serial_sbi.c @@ -0,0 +1,77 @@ +#define DEBUG +#define DBG() printf("%s:%s:%d\n", __FILE__, __func__, __LINE__) +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Anup Patel + */ + +#include +#include +#include +#include +#include +#include + +struct sbi_serial_priv { + struct console_device cdev; + uint8_t b[16], head, tail; +}; + +#define to_priv(cdev) container_of(cdev, struct sbi_serial_priv, cdev) + +static int sbi_serial_getc(struct console_device *cdev) +{ + struct sbi_serial_priv *priv = cdev->dev->priv; + if (priv->head == priv->tail) + return 0; + return priv->b[priv->head++ & 0xf]; +} + +static void sbi_serial_putc(struct console_device *cdev, const char ch) +{ + sbi_console_putchar(ch); +} + +static int sbi_serial_tstc(struct console_device *cdev) +{ + struct sbi_serial_priv *priv = cdev->dev->priv; + int c = sbi_console_getchar(); + + if (c != -1) + priv->b[priv->tail++ & 0xf] = c; + return priv->head != priv->tail; +} +static void sbi_serial_flush(struct console_device *cdev) +{ +} +static int sbi_serial_setbrg(struct console_device *cdev, int _) +{ + return 0; +} + +static int sbi_serial_probe(struct device_d *dev) +{ + struct sbi_serial_priv *priv; + + dev->priv = priv = xzalloc(sizeof(*priv)); + priv->cdev.dev = dev; + priv->cdev.putc = sbi_serial_putc; + priv->cdev.getc = sbi_serial_getc; + priv->cdev.tstc = sbi_serial_tstc; + priv->cdev.flush = sbi_serial_flush; + priv->cdev.setbrg = sbi_serial_setbrg; + + return console_register(&priv->cdev); +} + +static __maybe_unused struct of_device_id sbi_serial_dt_ids[] = { + { .compatible = "ucb,htif0" }, + { /* sentinel */ } +}; + +static struct driver_d serial_sbi_driver = { + .name = "serial_sbi", + .probe = sbi_serial_probe, + .of_compatible = sbi_serial_dt_ids, +}; +console_platform_driver(serial_sbi_driver); -- 2.32.0