Tom Rini 2022-02-10 15:09:55 -05:00
commit c4408291bf
6 changed files with 232 additions and 16 deletions

View File

@ -56,6 +56,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
imply DM_SCSI imply DM_SCSI
imply SYS_NS16550 imply SYS_NS16550
imply SIFIVE_SERIAL imply SIFIVE_SERIAL
imply HTIF_CONSOLE if 64BIT
imply SYSRESET imply SYSRESET
imply SYSRESET_CMD_POWEROFF imply SYSRESET_CMD_POWEROFF
imply SYSRESET_SYSCON imply SYSRESET_SYSCON

View File

@ -5,6 +5,7 @@
#include <common.h> #include <common.h>
#include <dm.h> #include <dm.h>
#include <dm/ofnode.h>
#include <env.h> #include <env.h>
#include <fdtdec.h> #include <fdtdec.h>
#include <image.h> #include <image.h>
@ -16,6 +17,17 @@
DECLARE_GLOBAL_DATA_PTR; 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) int board_init(void)
{ {
/* /*

View File

@ -4,19 +4,24 @@
QEMU RISC-V QEMU RISC-V
=========== ===========
QEMU for RISC-V supports a special 'virt' machine designed for emulation and QEMU for RISC-V supports a special 'virt' machine and 'spike' machine designed
virtualization purposes. This document describes how to run U-Boot under it. for emulation and virtualization purposes. This document describes how to run
Both 32-bit and 64-bit targets are supported, running in either machine or U-Boot under it. Both 32-bit and 64-bit targets are supported, running in
supervisor mode. either machine or supervisor mode.
The QEMU virt machine models a generic RISC-V virtual machine with support for 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, 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 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 See :doc:`../../develop/devicetree/dt_qemu` for information on how to see
the devicetree actually generated by QEMU. 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 Building U-Boot
--------------- ---------------
@ -41,13 +46,17 @@ Running U-Boot
-------------- --------------
The minimal QEMU command line to get U-Boot up and running is: 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 qemu-system-riscv64 -nographic -machine virt -bios u-boot.bin
- For 64-bit RISC-V spike machine::
qemu-system-riscv64 -nographic -machine spike -bios u-boot.bin
The commands above create targets with 128MiB memory by default. The commands above create targets with 128MiB memory by default.
A freely configurable amount of RAM can be created via the '-m' 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 For instructions on how to run U-Boot in supervisor mode on QEMU
with OpenSBI, see the documentation available with OpenSBI: 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/qemu_virt.md
https://github.com/riscv/opensbi/blob/master/docs/platform/spike.md
These have been tested in QEMU 5.0.0. 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: 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/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 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 its location with the OPENSBI environment variable. Afterwards, compile U-Boot
with the following commands. 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 The minimal QEMU commands to run U-Boot SPL in both 32-bit and 64-bit
configurations are: 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 -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 \ qemu-system-riscv64 -nographic -machine virt -bios spl/u-boot-spl.bin \
-device loader,file=u-boot.itb,addr=0x80200000 -device loader,file=u-boot.itb,addr=0x80200000
An attached disk can be emulated by adding:: - For 64-bit RISC-V spike machine::
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 in RISC-V virt machine by adding::
-device ich9-ahci,id=ahci \ -device ich9-ahci,id=ahci \
-drive if=none,file=riscv64.img,format=raw,id=mydisk \ -drive if=none,file=riscv64.img,format=raw,id=mydisk \

View File

@ -866,6 +866,14 @@ config PXA_SERIAL
If you have a machine based on a Marvell XScale PXA2xx CPU you If you have a machine based on a Marvell XScale PXA2xx CPU you
can enable its onboard serial ports by enabling this option. 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 config SIFIVE_SERIAL
bool "SiFive UART support" bool "SiFive UART support"
depends on DM_SERIAL depends on DM_SERIAL

View File

@ -73,6 +73,7 @@ obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o
obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o
obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
obj-$(CONFIG_XEN_SERIAL) += serial_xen.o obj-$(CONFIG_XEN_SERIAL) += serial_xen.o

View File

@ -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,
};