summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-02-10 23:09:55 +0300
committerTom Rini <trini@konsulko.com>2022-02-10 23:09:55 +0300
commitc4408291bfff9622f2d3817a13c997debd0e8200 (patch)
tree3828b8cf7fc4ff57487c55acf6f7f237e8bb4113
parent2ccd2bc8c3580e00c51094c5cc2b3e2ead8d35c3 (diff)
parent7c08680aa32db12e5a7e2765cfc8b7e8ce8895ff (diff)
downloadu-boot-c4408291bfff9622f2d3817a13c997debd0e8200.tar.xz
Merge https://source.denx.de/u-boot/custodians/u-boot-riscv
-rw-r--r--board/emulation/qemu-riscv/Kconfig1
-rw-r--r--board/emulation/qemu-riscv/qemu-riscv.c12
-rw-r--r--doc/board/emulation/qemu-riscv.rst48
-rw-r--r--drivers/serial/Kconfig8
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial_htif.c178
6 files changed, 232 insertions, 16 deletions
diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig
index a380db61a0..02bf84725b 100644
--- a/board/emulation/qemu-riscv/Kconfig
+++ b/board/emulation/qemu-riscv/Kconfig
@@ -56,6 +56,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
imply DM_SCSI
imply SYS_NS16550
imply SIFIVE_SERIAL
+ imply HTIF_CONSOLE if 64BIT
imply SYSRESET
imply SYSRESET_CMD_POWEROFF
imply SYSRESET_SYSCON
diff --git a/board/emulation/qemu-riscv/qemu-riscv.c b/board/emulation/qemu-riscv/qemu-riscv.c
index b0d9dd59b1..ae3b7a3295 100644
--- a/board/emulation/qemu-riscv/qemu-riscv.c
+++ b/board/emulation/qemu-riscv/qemu-riscv.c
@@ -5,6 +5,7 @@
#include <common.h>
#include <dm.h>
+#include <dm/ofnode.h>
#include <env.h>
#include <fdtdec.h>
#include <image.h>
@@ -16,6 +17,17 @@
DECLARE_GLOBAL_DATA_PTR;
+#if IS_ENABLED(CONFIG_MTD_NOR_FLASH)
+int is_flash_available(void)
+{
+ if (!ofnode_equal(ofnode_by_compatible(ofnode_null(), "cfi-flash"),
+ ofnode_null()))
+ return 1;
+
+ return 0;
+}
+#endif
+
int board_init(void)
{
/*
diff --git a/doc/board/emulation/qemu-riscv.rst b/doc/board/emulation/qemu-riscv.rst
index 3409fff811..ae998810c8 100644
--- a/doc/board/emulation/qemu-riscv.rst
+++ b/doc/board/emulation/qemu-riscv.rst
@@ -4,19 +4,24 @@
QEMU RISC-V
===========
-QEMU for RISC-V supports a special 'virt' machine designed for emulation and
-virtualization purposes. This document describes how to run U-Boot under it.
-Both 32-bit and 64-bit targets are supported, running in either machine or
-supervisor mode.
+QEMU for RISC-V supports a special 'virt' machine and 'spike' machine designed
+for emulation and virtualization purposes. This document describes how to run
+U-Boot under it. Both 32-bit and 64-bit targets are supported, running in
+either machine or supervisor mode.
The QEMU virt machine models a generic RISC-V virtual machine with support for
the VirtIO standard networking and block storage devices. It has CLINT, PLIC,
16550A UART devices in addition to VirtIO and it also uses device-tree to pass
-configuration information to guest software. It implements RISC-V privileged
+configuration information to guest software. It implements the latest RISC-V
+privileged architecture.
See :doc:`../../develop/devicetree/dt_qemu` for information on how to see
the devicetree actually generated by QEMU.
-architecture spec v1.10.
+
+The QEMU spike machine models a minimalistic RISC-V virtual machine with
+only CLINT and HTIF devices. It also uses device-tree to pass configuration
+information to guest software and implements the latest RISC-V privileged
+architecture.
Building U-Boot
---------------
@@ -41,13 +46,17 @@ Running U-Boot
--------------
The minimal QEMU command line to get U-Boot up and running is:
-- For 32-bit RISC-V::
+- For 32-bit RISC-V virt machine::
- qemu-system-riscv32 -nographic -machine virt -bios u-boot
+ qemu-system-riscv32 -nographic -machine virt -bios u-boot.bin
-- For 64-bit RISC-V::
+- For 64-bit RISC-V virt machine::
+
+ qemu-system-riscv64 -nographic -machine virt -bios u-boot.bin
+
+- For 64-bit RISC-V spike machine::
- qemu-system-riscv64 -nographic -machine virt -bios u-boot
+ qemu-system-riscv64 -nographic -machine spike -bios u-boot.bin
The commands above create targets with 128MiB memory by default.
A freely configurable amount of RAM can be created via the '-m'
@@ -58,6 +67,7 @@ the new setting.
For instructions on how to run U-Boot in supervisor mode on QEMU
with OpenSBI, see the documentation available with OpenSBI:
https://github.com/riscv/opensbi/blob/master/docs/platform/qemu_virt.md
+https://github.com/riscv/opensbi/blob/master/docs/platform/spike.md
These have been tested in QEMU 5.0.0.
@@ -80,8 +90,9 @@ supported by U-Boot. Clone the OpenSBI repository and run the following command.
See the OpenSBI documentation for full details:
https://github.com/riscv/opensbi/blob/master/docs/platform/qemu_virt.md
+https://github.com/riscv/opensbi/blob/master/docs/platform/spike.md
-To make the FW_DYNAMIC binary (build/platform/qemu/virt/firmware/fw_dynamic.bin)
+To make the FW_DYNAMIC binary (build/platform/generic/firmware/fw_dynamic.bin)
available to U-Boot, either copy it into the U-Boot root directory or specify
its location with the OPENSBI environment variable. Afterwards, compile U-Boot
with the following commands.
@@ -99,17 +110,22 @@ with the following commands.
The minimal QEMU commands to run U-Boot SPL in both 32-bit and 64-bit
configurations are:
-- For 32-bit RISC-V::
+- For 32-bit RISC-V virt machine::
- qemu-system-riscv32 -nographic -machine virt -bios spl/u-boot-spl \
+ qemu-system-riscv32 -nographic -machine virt -bios spl/u-boot-spl.bin \
-device loader,file=u-boot.itb,addr=0x80200000
-- For 64-bit RISC-V::
+- For 64-bit RISC-V virt machine::
+
+ qemu-system-riscv64 -nographic -machine virt -bios spl/u-boot-spl.bin \
+ -device loader,file=u-boot.itb,addr=0x80200000
+
+- For 64-bit RISC-V spike machine::
- qemu-system-riscv64 -nographic -machine virt -bios spl/u-boot-spl \
+ qemu-system-riscv64 -nographic -machine spike -bios spl/u-boot-spl.bin \
-device loader,file=u-boot.itb,addr=0x80200000
-An attached disk can be emulated by adding::
+An attached disk can be emulated in RISC-V virt machine by adding::
-device ich9-ahci,id=ahci \
-drive if=none,file=riscv64.img,format=raw,id=mydisk \
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 6c8fdda9a0..345d1881f5 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -866,6 +866,14 @@ config PXA_SERIAL
If you have a machine based on a Marvell XScale PXA2xx CPU you
can enable its onboard serial ports by enabling this option.
+config HTIF_CONSOLE
+ bool "RISC-V HTIF console support"
+ depends on DM_SERIAL && 64BIT
+ help
+ Select this to enable host transfer interface (HTIF) based serial
+ console. The HTIF device is quite common in RISC-V emulators and
+ RISC-V ISS so this driver allows using U-Boot on such platforms.
+
config SIFIVE_SERIAL
bool "SiFive UART support"
depends on DM_SERIAL
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 8168af640f..52e70aa191 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
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
diff --git a/drivers/serial/serial_htif.c b/drivers/serial/serial_htif.c
new file mode 100644
index 0000000000..5d2bf0aaeb
--- /dev/null
+++ b/drivers/serial/serial_htif.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Ventana Micro Systems Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define HTIF_DATA_BITS 48
+#define HTIF_DATA_MASK ((1ULL << HTIF_DATA_BITS) - 1)
+#define HTIF_DATA_SHIFT 0
+#define HTIF_CMD_BITS 8
+#define HTIF_CMD_MASK ((1ULL << HTIF_CMD_BITS) - 1)
+#define HTIF_CMD_SHIFT 48
+#define HTIF_DEV_BITS 8
+#define HTIF_DEV_MASK ((1ULL << HTIF_DEV_BITS) - 1)
+#define HTIF_DEV_SHIFT 56
+
+#define HTIF_DEV_SYSTEM 0
+#define HTIF_DEV_CONSOLE 1
+
+#define HTIF_CONSOLE_CMD_GETC 0
+#define HTIF_CONSOLE_CMD_PUTC 1
+
+#if __riscv_xlen == 64
+# define TOHOST_CMD(dev, cmd, payload) \
+ (((u64)(dev) << HTIF_DEV_SHIFT) | \
+ ((u64)(cmd) << HTIF_CMD_SHIFT) | \
+ (u64)(payload))
+#else
+# define TOHOST_CMD(dev, cmd, payload) ({ \
+ if ((dev) || (cmd)) \
+ __builtin_trap(); \
+ (payload); })
+#endif
+#define FROMHOST_DEV(fromhost_value) \
+ ((u64)((fromhost_value) >> HTIF_DEV_SHIFT) & HTIF_DEV_MASK)
+#define FROMHOST_CMD(fromhost_value) \
+ ((u64)((fromhost_value) >> HTIF_CMD_SHIFT) & HTIF_CMD_MASK)
+#define FROMHOST_DATA(fromhost_value) \
+ ((u64)((fromhost_value) >> HTIF_DATA_SHIFT) & HTIF_DATA_MASK)
+
+struct htif_plat {
+ void *fromhost;
+ void *tohost;
+ int console_char;
+};
+
+static void __check_fromhost(struct htif_plat *plat)
+{
+ u64 fh = readq(plat->fromhost);
+
+ if (!fh)
+ return;
+ writeq(0, plat->fromhost);
+
+ /* this should be from the console */
+ if (FROMHOST_DEV(fh) != HTIF_DEV_CONSOLE)
+ __builtin_trap();
+ switch (FROMHOST_CMD(fh)) {
+ case HTIF_CONSOLE_CMD_GETC:
+ plat->console_char = 1 + (u8)FROMHOST_DATA(fh);
+ break;
+ case HTIF_CONSOLE_CMD_PUTC:
+ break;
+ default:
+ __builtin_trap();
+ }
+}
+
+static void __set_tohost(struct htif_plat *plat,
+ u64 dev, u64 cmd, u64 data)
+{
+ while (readq(plat->tohost))
+ __check_fromhost(plat);
+ writeq(TOHOST_CMD(dev, cmd, data), plat->tohost);
+}
+
+static int htif_serial_putc(struct udevice *dev, const char ch)
+{
+ struct htif_plat *plat = dev_get_plat(dev);
+
+ __set_tohost(plat, HTIF_DEV_CONSOLE, HTIF_CONSOLE_CMD_PUTC, ch);
+ return 0;
+}
+
+static int htif_serial_getc(struct udevice *dev)
+{
+ int ch;
+ struct htif_plat *plat = dev_get_plat(dev);
+
+ if (plat->console_char < 0)
+ __check_fromhost(plat);
+
+ if (plat->console_char >= 0) {
+ ch = plat->console_char;
+ plat->console_char = -1;
+ __set_tohost(plat, HTIF_DEV_CONSOLE, HTIF_CONSOLE_CMD_GETC, 0);
+ return (ch) ? ch - 1 : -EAGAIN;
+ }
+
+ return -EAGAIN;
+}
+
+static int htif_serial_pending(struct udevice *dev, bool input)
+{
+ struct htif_plat *plat = dev_get_plat(dev);
+
+ if (!input)
+ return 0;
+
+ if (plat->console_char < 0)
+ __check_fromhost(plat);
+
+ return (plat->console_char >= 0) ? 1 : 0;
+}
+
+static int htif_serial_probe(struct udevice *dev)
+{
+ struct htif_plat *plat = dev_get_plat(dev);
+
+ /* Queue first getc request */
+ __set_tohost(plat, HTIF_DEV_CONSOLE, HTIF_CONSOLE_CMD_GETC, 0);
+
+ return 0;
+}
+
+static int htif_serial_of_to_plat(struct udevice *dev)
+{
+ fdt_addr_t addr;
+ struct htif_plat *plat = dev_get_plat(dev);
+
+ addr = dev_read_addr_index(dev, 0);
+ if (addr == FDT_ADDR_T_NONE)
+ return -ENODEV;
+ plat->fromhost = (void *)(uintptr_t)addr;
+ plat->tohost = plat->fromhost + sizeof(u64);
+
+ addr = dev_read_addr_index(dev, 1);
+ if (addr != FDT_ADDR_T_NONE)
+ plat->tohost = (void *)(uintptr_t)addr;
+
+ plat->console_char = -1;
+
+ return 0;
+}
+
+static const struct dm_serial_ops htif_serial_ops = {
+ .putc = htif_serial_putc,
+ .getc = htif_serial_getc,
+ .pending = htif_serial_pending,
+};
+
+static const struct udevice_id htif_serial_ids[] = {
+ { .compatible = "ucb,htif0" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_htif) = {
+ .name = "serial_htif",
+ .id = UCLASS_SERIAL,
+ .of_match = htif_serial_ids,
+ .of_to_plat = htif_serial_of_to_plat,
+ .plat_auto = sizeof(struct htif_plat),
+ .probe = htif_serial_probe,
+ .ops = &htif_serial_ops,
+};