mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-19 21:51:31 +00:00
Merge git://git.denx.de/u-boot-riscv
- Add DM drivers to support RISC-V CPU and timer, plus some bug fixes. - Support SiFive UART - Rename ax25-ae350 defconfig
This commit is contained in:
commit
328e3f8a70
37 changed files with 1156 additions and 411 deletions
|
@ -22,6 +22,7 @@ source "board/emulation/qemu-riscv/Kconfig"
|
||||||
|
|
||||||
# platform-specific options below
|
# platform-specific options below
|
||||||
source "arch/riscv/cpu/ax25/Kconfig"
|
source "arch/riscv/cpu/ax25/Kconfig"
|
||||||
|
source "arch/riscv/cpu/qemu/Kconfig"
|
||||||
|
|
||||||
# architecture-specific options below
|
# architecture-specific options below
|
||||||
|
|
||||||
|
@ -44,6 +45,40 @@ config ARCH_RV64I
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Code Model"
|
||||||
|
default CMODEL_MEDLOW
|
||||||
|
|
||||||
|
config CMODEL_MEDLOW
|
||||||
|
bool "medium low code model"
|
||||||
|
help
|
||||||
|
U-Boot and its statically defined symbols must lie within a single 2 GiB
|
||||||
|
address range and must lie between absolute addresses -2 GiB and +2 GiB.
|
||||||
|
|
||||||
|
config CMODEL_MEDANY
|
||||||
|
bool "medium any code model"
|
||||||
|
help
|
||||||
|
U-Boot and its statically defined symbols must be within any single 2 GiB
|
||||||
|
address range.
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Run Mode"
|
||||||
|
default RISCV_MMODE
|
||||||
|
|
||||||
|
config RISCV_MMODE
|
||||||
|
bool "Machine"
|
||||||
|
help
|
||||||
|
Choose this option to build U-Boot for RISC-V M-Mode.
|
||||||
|
|
||||||
|
config RISCV_SMODE
|
||||||
|
bool "Supervisor"
|
||||||
|
help
|
||||||
|
Choose this option to build U-Boot for RISC-V S-Mode.
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
config RISCV_ISA_C
|
config RISCV_ISA_C
|
||||||
bool "Emit compressed instructions"
|
bool "Emit compressed instructions"
|
||||||
default y
|
default y
|
||||||
|
@ -55,15 +90,30 @@ config RISCV_ISA_C
|
||||||
config RISCV_ISA_A
|
config RISCV_ISA_A
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
config RISCV_SMODE
|
|
||||||
bool "Run in S-Mode"
|
|
||||||
help
|
|
||||||
Enable this option to build U-Boot for RISC-V S-Mode
|
|
||||||
|
|
||||||
config 32BIT
|
config 32BIT
|
||||||
bool
|
bool
|
||||||
|
|
||||||
config 64BIT
|
config 64BIT
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config SIFIVE_CLINT
|
||||||
|
bool
|
||||||
|
depends on RISCV_MMODE
|
||||||
|
select REGMAP
|
||||||
|
select SYSCON
|
||||||
|
help
|
||||||
|
The SiFive CLINT block holds memory-mapped control and status registers
|
||||||
|
associated with software and timer interrupts.
|
||||||
|
|
||||||
|
config RISCV_RDTIME
|
||||||
|
bool
|
||||||
|
default y if RISCV_SMODE
|
||||||
|
help
|
||||||
|
The provides the riscv_get_time() API that is implemented using the
|
||||||
|
standard rdtime instruction. This is the case for S-mode U-Boot, and
|
||||||
|
is useful for processors that support rdtime in M-mode too.
|
||||||
|
|
||||||
|
config SYS_MALLOC_F_LEN
|
||||||
|
default 0x1000
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -17,8 +17,15 @@ endif
|
||||||
ifeq ($(CONFIG_RISCV_ISA_C),y)
|
ifeq ($(CONFIG_RISCV_ISA_C),y)
|
||||||
ARCH_C = c
|
ARCH_C = c
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(CONFIG_CMODEL_MEDLOW),y)
|
||||||
|
CMODEL = medlow
|
||||||
|
endif
|
||||||
|
ifeq ($(CONFIG_CMODEL_MEDANY),y)
|
||||||
|
CMODEL = medany
|
||||||
|
endif
|
||||||
|
|
||||||
ARCH_FLAGS = -march=$(ARCH_BASE)$(ARCH_A)$(ARCH_C) -mabi=$(ABI)
|
ARCH_FLAGS = -march=$(ARCH_BASE)$(ARCH_A)$(ARCH_C) -mabi=$(ABI) \
|
||||||
|
-mcmodel=$(CMODEL)
|
||||||
|
|
||||||
PLATFORM_CPPFLAGS += $(ARCH_FLAGS)
|
PLATFORM_CPPFLAGS += $(ARCH_FLAGS)
|
||||||
CFLAGS_EFI += $(ARCH_FLAGS)
|
CFLAGS_EFI += $(ARCH_FLAGS)
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
|
|
||||||
extra-y = start.o
|
extra-y = start.o
|
||||||
|
|
||||||
obj-y += cpu.o
|
obj-y += cpu.o mtrap.o
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
config RISCV_NDS
|
config RISCV_NDS
|
||||||
bool "AndeStar V5 ISA support"
|
bool
|
||||||
default n
|
|
||||||
help
|
help
|
||||||
Say Y here if you plan to run U-Boot on AndeStar v5
|
Run U-Boot on AndeStar V5 platforms and use some specific features
|
||||||
platforms and use some specific features which are
|
which are provided by Andes Technology AndeStar V5 families.
|
||||||
provided by Andes Technology AndeStar V5 Families.
|
|
||||||
|
if RISCV_NDS
|
||||||
|
|
||||||
|
config RISCV_NDS_CACHE
|
||||||
|
bool "AndeStar V5 families specific cache support"
|
||||||
|
help
|
||||||
|
Provide Andes Technology AndeStar V5 families specific cache support.
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
void icache_enable(void)
|
void icache_enable(void)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SYS_ICACHE_OFF
|
#ifndef CONFIG_SYS_ICACHE_OFF
|
||||||
#ifdef CONFIG_RISCV_NDS
|
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"csrr t1, mcache_ctl\n\t"
|
"csrr t1, mcache_ctl\n\t"
|
||||||
"ori t0, t1, 0x1\n\t"
|
"ori t0, t1, 0x1\n\t"
|
||||||
|
@ -22,7 +22,7 @@ void icache_enable(void)
|
||||||
void icache_disable(void)
|
void icache_disable(void)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SYS_ICACHE_OFF
|
#ifndef CONFIG_SYS_ICACHE_OFF
|
||||||
#ifdef CONFIG_RISCV_NDS
|
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"fence.i\n\t"
|
"fence.i\n\t"
|
||||||
"csrr t1, mcache_ctl\n\t"
|
"csrr t1, mcache_ctl\n\t"
|
||||||
|
@ -36,7 +36,7 @@ void icache_disable(void)
|
||||||
void dcache_enable(void)
|
void dcache_enable(void)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SYS_DCACHE_OFF
|
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||||
#ifdef CONFIG_RISCV_NDS
|
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"csrr t1, mcache_ctl\n\t"
|
"csrr t1, mcache_ctl\n\t"
|
||||||
"ori t0, t1, 0x2\n\t"
|
"ori t0, t1, 0x2\n\t"
|
||||||
|
@ -49,7 +49,7 @@ void dcache_enable(void)
|
||||||
void dcache_disable(void)
|
void dcache_disable(void)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SYS_DCACHE_OFF
|
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||||
#ifdef CONFIG_RISCV_NDS
|
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"fence\n\t"
|
"fence\n\t"
|
||||||
"csrr t1, mcache_ctl\n\t"
|
"csrr t1, mcache_ctl\n\t"
|
||||||
|
@ -64,7 +64,7 @@ int icache_status(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_RISCV_NDS
|
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"csrr t1, mcache_ctl\n\t"
|
"csrr t1, mcache_ctl\n\t"
|
||||||
"andi %0, t1, 0x01\n\t"
|
"andi %0, t1, 0x01\n\t"
|
||||||
|
@ -81,7 +81,7 @@ int dcache_status(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_RISCV_NDS
|
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"csrr t1, mcache_ctl\n\t"
|
"csrr t1, mcache_ctl\n\t"
|
||||||
"andi %0, t1, 0x02\n\t"
|
"andi %0, t1, 0x02\n\t"
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <cpu.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <log.h>
|
||||||
#include <asm/csr.h>
|
#include <asm/csr.h>
|
||||||
|
#include <asm/encoding.h>
|
||||||
|
#include <dm/uclass-internal.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prior_stage_fdt_address must be stored in the data section since it is used
|
* prior_stage_fdt_address must be stored in the data section since it is used
|
||||||
|
@ -12,44 +17,79 @@
|
||||||
*/
|
*/
|
||||||
phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
|
phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
|
||||||
|
|
||||||
enum {
|
|
||||||
ISA_INVALID = 0,
|
|
||||||
ISA_32BIT,
|
|
||||||
ISA_64BIT,
|
|
||||||
ISA_128BIT
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char * const isa_bits[] = {
|
|
||||||
[ISA_INVALID] = NULL,
|
|
||||||
[ISA_32BIT] = "32",
|
|
||||||
[ISA_64BIT] = "64",
|
|
||||||
[ISA_128BIT] = "128"
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline bool supports_extension(char ext)
|
static inline bool supports_extension(char ext)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_CPU
|
||||||
|
struct udevice *dev;
|
||||||
|
char desc[32];
|
||||||
|
|
||||||
|
uclass_find_first_device(UCLASS_CPU, &dev);
|
||||||
|
if (!dev) {
|
||||||
|
debug("unable to find the RISC-V cpu device\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!cpu_get_desc(dev, desc, sizeof(desc))) {
|
||||||
|
/* skip the first 4 characters (rv32|rv64) */
|
||||||
|
if (strchr(desc + 4, ext))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
#else /* !CONFIG_CPU */
|
||||||
|
#ifdef CONFIG_RISCV_MMODE
|
||||||
return csr_read(misa) & (1 << (ext - 'a'));
|
return csr_read(misa) & (1 << (ext - 'a'));
|
||||||
|
#else /* !CONFIG_RISCV_MMODE */
|
||||||
|
#warning "There is no way to determine the available extensions in S-mode."
|
||||||
|
#warning "Please convert your board to use the RISC-V CPU driver."
|
||||||
|
return false;
|
||||||
|
#endif /* CONFIG_RISCV_MMODE */
|
||||||
|
#endif /* CONFIG_CPU */
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
static int riscv_cpu_probe(void)
|
||||||
{
|
{
|
||||||
char name[32];
|
#ifdef CONFIG_CPU
|
||||||
char *s = name;
|
int ret;
|
||||||
int bit;
|
|
||||||
|
|
||||||
s += sprintf(name, "rv");
|
/* probe cpus so that RISC-V timer can be bound */
|
||||||
bit = csr_read(misa) >> (sizeof(long) * 8 - 2);
|
ret = cpu_probe_all();
|
||||||
s += sprintf(s, isa_bits[bit]);
|
if (ret)
|
||||||
|
return log_msg_ret("RISC-V cpus probe failed\n", ret);
|
||||||
supports_extension('i') ? *s++ = 'i' : 'r';
|
#endif
|
||||||
supports_extension('m') ? *s++ = 'm' : 'i';
|
|
||||||
supports_extension('a') ? *s++ = 'a' : 's';
|
|
||||||
supports_extension('f') ? *s++ = 'f' : 'c';
|
|
||||||
supports_extension('d') ? *s++ = 'd' : '-';
|
|
||||||
supports_extension('c') ? *s++ = 'c' : 'v';
|
|
||||||
*s++ = '\0';
|
|
||||||
|
|
||||||
printf("CPU: %s\n", name);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int arch_cpu_init_dm(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = riscv_cpu_probe();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Enable FPU */
|
||||||
|
if (supports_extension('d') || supports_extension('f')) {
|
||||||
|
csr_set(MODE_PREFIX(status), MSTATUS_FS);
|
||||||
|
csr_write(fcsr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONFIG_IS_ENABLED(RISCV_MMODE)) {
|
||||||
|
/*
|
||||||
|
* Enable perf counters for cycle, time,
|
||||||
|
* and instret counters only
|
||||||
|
*/
|
||||||
|
csr_write(mcounteren, GENMASK(2, 0));
|
||||||
|
|
||||||
|
/* Disable paging */
|
||||||
|
if (supports_extension('s'))
|
||||||
|
csr_write(satp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arch_early_init_r(void)
|
||||||
|
{
|
||||||
|
return riscv_cpu_probe();
|
||||||
|
}
|
||||||
|
|
103
arch/riscv/cpu/mtrap.S
Normal file
103
arch/riscv/cpu/mtrap.S
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* M-mode Trap Handler Code for RISC-V Core
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Microsemi Corporation.
|
||||||
|
* Copyright (c) 2017 Padmarao Begari <Padmarao.Begari@microsemi.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Andes Technology Corporation
|
||||||
|
* Rick Chen, Andes Technology Corporation <rick@andestech.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <asm/encoding.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
|
#define LREG lw
|
||||||
|
#define SREG sw
|
||||||
|
#define REGBYTES 4
|
||||||
|
#else
|
||||||
|
#define LREG ld
|
||||||
|
#define SREG sd
|
||||||
|
#define REGBYTES 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
/* trap entry */
|
||||||
|
.align 2
|
||||||
|
.global trap_entry
|
||||||
|
trap_entry:
|
||||||
|
addi sp, sp, -32 * REGBYTES
|
||||||
|
SREG x1, 1 * REGBYTES(sp)
|
||||||
|
SREG x2, 2 * REGBYTES(sp)
|
||||||
|
SREG x3, 3 * REGBYTES(sp)
|
||||||
|
SREG x4, 4 * REGBYTES(sp)
|
||||||
|
SREG x5, 5 * REGBYTES(sp)
|
||||||
|
SREG x6, 6 * REGBYTES(sp)
|
||||||
|
SREG x7, 7 * REGBYTES(sp)
|
||||||
|
SREG x8, 8 * REGBYTES(sp)
|
||||||
|
SREG x9, 9 * REGBYTES(sp)
|
||||||
|
SREG x10, 10 * REGBYTES(sp)
|
||||||
|
SREG x11, 11 * REGBYTES(sp)
|
||||||
|
SREG x12, 12 * REGBYTES(sp)
|
||||||
|
SREG x13, 13 * REGBYTES(sp)
|
||||||
|
SREG x14, 14 * REGBYTES(sp)
|
||||||
|
SREG x15, 15 * REGBYTES(sp)
|
||||||
|
SREG x16, 16 * REGBYTES(sp)
|
||||||
|
SREG x17, 17 * REGBYTES(sp)
|
||||||
|
SREG x18, 18 * REGBYTES(sp)
|
||||||
|
SREG x19, 19 * REGBYTES(sp)
|
||||||
|
SREG x20, 20 * REGBYTES(sp)
|
||||||
|
SREG x21, 21 * REGBYTES(sp)
|
||||||
|
SREG x22, 22 * REGBYTES(sp)
|
||||||
|
SREG x23, 23 * REGBYTES(sp)
|
||||||
|
SREG x24, 24 * REGBYTES(sp)
|
||||||
|
SREG x25, 25 * REGBYTES(sp)
|
||||||
|
SREG x26, 26 * REGBYTES(sp)
|
||||||
|
SREG x27, 27 * REGBYTES(sp)
|
||||||
|
SREG x28, 28 * REGBYTES(sp)
|
||||||
|
SREG x29, 29 * REGBYTES(sp)
|
||||||
|
SREG x30, 30 * REGBYTES(sp)
|
||||||
|
SREG x31, 31 * REGBYTES(sp)
|
||||||
|
csrr a0, MODE_PREFIX(cause)
|
||||||
|
csrr a1, MODE_PREFIX(epc)
|
||||||
|
mv a2, sp
|
||||||
|
jal handle_trap
|
||||||
|
csrw MODE_PREFIX(epc), a0
|
||||||
|
|
||||||
|
LREG x1, 1 * REGBYTES(sp)
|
||||||
|
LREG x3, 3 * REGBYTES(sp)
|
||||||
|
LREG x4, 4 * REGBYTES(sp)
|
||||||
|
LREG x5, 5 * REGBYTES(sp)
|
||||||
|
LREG x6, 6 * REGBYTES(sp)
|
||||||
|
LREG x7, 7 * REGBYTES(sp)
|
||||||
|
LREG x8, 8 * REGBYTES(sp)
|
||||||
|
LREG x9, 9 * REGBYTES(sp)
|
||||||
|
LREG x10, 10 * REGBYTES(sp)
|
||||||
|
LREG x11, 11 * REGBYTES(sp)
|
||||||
|
LREG x12, 12 * REGBYTES(sp)
|
||||||
|
LREG x13, 13 * REGBYTES(sp)
|
||||||
|
LREG x14, 14 * REGBYTES(sp)
|
||||||
|
LREG x15, 15 * REGBYTES(sp)
|
||||||
|
LREG x16, 16 * REGBYTES(sp)
|
||||||
|
LREG x17, 17 * REGBYTES(sp)
|
||||||
|
LREG x18, 18 * REGBYTES(sp)
|
||||||
|
LREG x19, 19 * REGBYTES(sp)
|
||||||
|
LREG x20, 20 * REGBYTES(sp)
|
||||||
|
LREG x21, 21 * REGBYTES(sp)
|
||||||
|
LREG x22, 22 * REGBYTES(sp)
|
||||||
|
LREG x23, 23 * REGBYTES(sp)
|
||||||
|
LREG x24, 24 * REGBYTES(sp)
|
||||||
|
LREG x25, 25 * REGBYTES(sp)
|
||||||
|
LREG x26, 26 * REGBYTES(sp)
|
||||||
|
LREG x27, 27 * REGBYTES(sp)
|
||||||
|
LREG x28, 28 * REGBYTES(sp)
|
||||||
|
LREG x29, 29 * REGBYTES(sp)
|
||||||
|
LREG x30, 30 * REGBYTES(sp)
|
||||||
|
LREG x31, 31 * REGBYTES(sp)
|
||||||
|
LREG x2, 2 * REGBYTES(sp)
|
||||||
|
addi sp, sp, 32 * REGBYTES
|
||||||
|
MODE_PREFIX(ret)
|
12
arch/riscv/cpu/qemu/Kconfig
Normal file
12
arch/riscv/cpu/qemu/Kconfig
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
|
||||||
|
config QEMU_RISCV
|
||||||
|
bool
|
||||||
|
select ARCH_EARLY_INIT_R
|
||||||
|
imply CPU
|
||||||
|
imply CPU_RISCV
|
||||||
|
imply RISCV_TIMER
|
||||||
|
imply SIFIVE_CLINT if RISCV_MMODE
|
||||||
|
imply CMD_CPU
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cleanup_before_linux() is called just before we call linux
|
* cleanup_before_linux() is called just before we call linux
|
||||||
|
@ -19,3 +20,16 @@ int cleanup_before_linux(void)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* To enumerate devices on the /soc/ node, create a "simple-bus" driver */
|
||||||
|
static const struct udevice_id riscv_virtio_soc_ids[] = {
|
||||||
|
{ .compatible = "riscv-virtio-soc" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(riscv_virtio_soc) = {
|
||||||
|
.name = "riscv_virtio_soc",
|
||||||
|
.id = UCLASS_SIMPLE_BUS,
|
||||||
|
.of_match = riscv_virtio_soc_ids,
|
||||||
|
.flags = DM_FLAG_PRE_RELOC,
|
||||||
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <asm/encoding.h>
|
#include <asm/encoding.h>
|
||||||
|
#include <generated/asm-offsets.h>
|
||||||
|
|
||||||
#ifdef CONFIG_32BIT
|
#ifdef CONFIG_32BIT
|
||||||
#define LREG lw
|
#define LREG lw
|
||||||
|
@ -70,6 +71,9 @@ call_board_init_f_0:
|
||||||
|
|
||||||
jal board_init_f_init_reserve
|
jal board_init_f_init_reserve
|
||||||
|
|
||||||
|
/* save the boot hart id to global_data */
|
||||||
|
SREG s0, GD_BOOT_HART(gp)
|
||||||
|
|
||||||
mv a0, zero /* a0 <-- boot_flags = 0 */
|
mv a0, zero /* a0 <-- boot_flags = 0 */
|
||||||
la t5, board_init_f
|
la t5, board_init_f
|
||||||
jr t5 /* jump to board_init_f() */
|
jr t5 /* jump to board_init_f() */
|
||||||
|
@ -198,92 +202,3 @@ call_board_init_r:
|
||||||
* jump to it ...
|
* jump to it ...
|
||||||
*/
|
*/
|
||||||
jr t4 /* jump to board_init_r() */
|
jr t4 /* jump to board_init_r() */
|
||||||
|
|
||||||
/*
|
|
||||||
* trap entry
|
|
||||||
*/
|
|
||||||
.align 2
|
|
||||||
trap_entry:
|
|
||||||
addi sp, sp, -32*REGBYTES
|
|
||||||
SREG x1, 1*REGBYTES(sp)
|
|
||||||
SREG x2, 2*REGBYTES(sp)
|
|
||||||
SREG x3, 3*REGBYTES(sp)
|
|
||||||
SREG x4, 4*REGBYTES(sp)
|
|
||||||
SREG x5, 5*REGBYTES(sp)
|
|
||||||
SREG x6, 6*REGBYTES(sp)
|
|
||||||
SREG x7, 7*REGBYTES(sp)
|
|
||||||
SREG x8, 8*REGBYTES(sp)
|
|
||||||
SREG x9, 9*REGBYTES(sp)
|
|
||||||
SREG x10, 10*REGBYTES(sp)
|
|
||||||
SREG x11, 11*REGBYTES(sp)
|
|
||||||
SREG x12, 12*REGBYTES(sp)
|
|
||||||
SREG x13, 13*REGBYTES(sp)
|
|
||||||
SREG x14, 14*REGBYTES(sp)
|
|
||||||
SREG x15, 15*REGBYTES(sp)
|
|
||||||
SREG x16, 16*REGBYTES(sp)
|
|
||||||
SREG x17, 17*REGBYTES(sp)
|
|
||||||
SREG x18, 18*REGBYTES(sp)
|
|
||||||
SREG x19, 19*REGBYTES(sp)
|
|
||||||
SREG x20, 20*REGBYTES(sp)
|
|
||||||
SREG x21, 21*REGBYTES(sp)
|
|
||||||
SREG x22, 22*REGBYTES(sp)
|
|
||||||
SREG x23, 23*REGBYTES(sp)
|
|
||||||
SREG x24, 24*REGBYTES(sp)
|
|
||||||
SREG x25, 25*REGBYTES(sp)
|
|
||||||
SREG x26, 26*REGBYTES(sp)
|
|
||||||
SREG x27, 27*REGBYTES(sp)
|
|
||||||
SREG x28, 28*REGBYTES(sp)
|
|
||||||
SREG x29, 29*REGBYTES(sp)
|
|
||||||
SREG x30, 30*REGBYTES(sp)
|
|
||||||
SREG x31, 31*REGBYTES(sp)
|
|
||||||
csrr a0, MODE_PREFIX(cause)
|
|
||||||
csrr a1, MODE_PREFIX(epc)
|
|
||||||
mv a2, sp
|
|
||||||
jal handle_trap
|
|
||||||
csrw MODE_PREFIX(epc), a0
|
|
||||||
|
|
||||||
#ifdef CONFIG_RISCV_SMODE
|
|
||||||
/*
|
|
||||||
* Remain in S-mode after sret
|
|
||||||
*/
|
|
||||||
li t0, SSTATUS_SPP
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* Remain in M-mode after mret
|
|
||||||
*/
|
|
||||||
li t0, MSTATUS_MPP
|
|
||||||
#endif
|
|
||||||
csrs MODE_PREFIX(status), t0
|
|
||||||
LREG x1, 1*REGBYTES(sp)
|
|
||||||
LREG x2, 2*REGBYTES(sp)
|
|
||||||
LREG x3, 3*REGBYTES(sp)
|
|
||||||
LREG x4, 4*REGBYTES(sp)
|
|
||||||
LREG x5, 5*REGBYTES(sp)
|
|
||||||
LREG x6, 6*REGBYTES(sp)
|
|
||||||
LREG x7, 7*REGBYTES(sp)
|
|
||||||
LREG x8, 8*REGBYTES(sp)
|
|
||||||
LREG x9, 9*REGBYTES(sp)
|
|
||||||
LREG x10, 10*REGBYTES(sp)
|
|
||||||
LREG x11, 11*REGBYTES(sp)
|
|
||||||
LREG x12, 12*REGBYTES(sp)
|
|
||||||
LREG x13, 13*REGBYTES(sp)
|
|
||||||
LREG x14, 14*REGBYTES(sp)
|
|
||||||
LREG x15, 15*REGBYTES(sp)
|
|
||||||
LREG x16, 16*REGBYTES(sp)
|
|
||||||
LREG x17, 17*REGBYTES(sp)
|
|
||||||
LREG x18, 18*REGBYTES(sp)
|
|
||||||
LREG x19, 19*REGBYTES(sp)
|
|
||||||
LREG x20, 20*REGBYTES(sp)
|
|
||||||
LREG x21, 21*REGBYTES(sp)
|
|
||||||
LREG x22, 22*REGBYTES(sp)
|
|
||||||
LREG x23, 23*REGBYTES(sp)
|
|
||||||
LREG x24, 24*REGBYTES(sp)
|
|
||||||
LREG x25, 25*REGBYTES(sp)
|
|
||||||
LREG x26, 26*REGBYTES(sp)
|
|
||||||
LREG x27, 27*REGBYTES(sp)
|
|
||||||
LREG x28, 28*REGBYTES(sp)
|
|
||||||
LREG x29, 29*REGBYTES(sp)
|
|
||||||
LREG x30, 30*REGBYTES(sp)
|
|
||||||
LREG x31, 31*REGBYTES(sp)
|
|
||||||
addi sp, sp, 32*REGBYTES
|
|
||||||
MODE_PREFIX(ret)
|
|
||||||
|
|
|
@ -1,229 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
#address-cells = <2>;
|
|
||||||
#size-cells = <2>;
|
|
||||||
compatible = "andestech,ax25";
|
|
||||||
model = "andestech,ax25";
|
|
||||||
|
|
||||||
aliases {
|
|
||||||
uart0 = &serial0;
|
|
||||||
spi0 = &spi;
|
|
||||||
};
|
|
||||||
|
|
||||||
chosen {
|
|
||||||
bootargs = "console=ttyS0,38400n8 debug loglevel=7";
|
|
||||||
stdout-path = "uart0:38400n8";
|
|
||||||
};
|
|
||||||
|
|
||||||
cpus {
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
timebase-frequency = <60000000>;
|
|
||||||
CPU0: cpu@0 {
|
|
||||||
device_type = "cpu";
|
|
||||||
reg = <0>;
|
|
||||||
status = "okay";
|
|
||||||
compatible = "riscv";
|
|
||||||
riscv,isa = "rv64imafdc";
|
|
||||||
mmu-type = "riscv,sv39";
|
|
||||||
clock-frequency = <60000000>;
|
|
||||||
d-cache-size = <0x8000>;
|
|
||||||
d-cache-line-size = <32>;
|
|
||||||
CPU0_intc: interrupt-controller {
|
|
||||||
#interrupt-cells = <1>;
|
|
||||||
interrupt-controller;
|
|
||||||
compatible = "riscv,cpu-intc";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
memory@0 {
|
|
||||||
device_type = "memory";
|
|
||||||
reg = <0x0 0x00000000 0x0 0x40000000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
soc {
|
|
||||||
#address-cells = <2>;
|
|
||||||
#size-cells = <2>;
|
|
||||||
compatible = "andestech,riscv-ae350-soc";
|
|
||||||
ranges;
|
|
||||||
|
|
||||||
plic0: interrupt-controller@e4000000 {
|
|
||||||
compatible = "riscv,plic0";
|
|
||||||
#address-cells = <2>;
|
|
||||||
#interrupt-cells = <2>;
|
|
||||||
interrupt-controller;
|
|
||||||
reg = <0x0 0xe4000000 0x0 0x2000000>;
|
|
||||||
riscv,ndev=<71>;
|
|
||||||
interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
|
|
||||||
};
|
|
||||||
|
|
||||||
plic1: interrupt-controller@e6400000 {
|
|
||||||
compatible = "riscv,plic1";
|
|
||||||
#address-cells = <2>;
|
|
||||||
#interrupt-cells = <2>;
|
|
||||||
interrupt-controller;
|
|
||||||
reg = <0x0 0xe6400000 0x0 0x400000>;
|
|
||||||
riscv,ndev=<1>;
|
|
||||||
interrupts-extended = <&CPU0_intc 3>;
|
|
||||||
};
|
|
||||||
|
|
||||||
plmt0@e6000000 {
|
|
||||||
compatible = "riscv,plmt0";
|
|
||||||
interrupts-extended = <&CPU0_intc 7>;
|
|
||||||
reg = <0x0 0xe6000000 0x0 0x100000>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
spiclk: virt_100mhz {
|
|
||||||
#clock-cells = <0>;
|
|
||||||
compatible = "fixed-clock";
|
|
||||||
clock-frequency = <100000000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
timer0: timer@f0400000 {
|
|
||||||
compatible = "andestech,atcpit100";
|
|
||||||
reg = <0x0 0xf0400000 0x0 0x1000>;
|
|
||||||
clock-frequency = <60000000>;
|
|
||||||
interrupts = <3 4>;
|
|
||||||
interrupt-parent = <&plic0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
serial0: serial@f0300000 {
|
|
||||||
compatible = "andestech,uart16550", "ns16550a";
|
|
||||||
reg = <0x0 0xf0300000 0x0 0x1000>;
|
|
||||||
interrupts = <9 4>;
|
|
||||||
clock-frequency = <19660800>;
|
|
||||||
reg-shift = <2>;
|
|
||||||
reg-offset = <32>;
|
|
||||||
no-loopback-test = <1>;
|
|
||||||
interrupt-parent = <&plic0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
mac0: mac@e0100000 {
|
|
||||||
compatible = "andestech,atmac100";
|
|
||||||
reg = <0x0 0xe0100000 0x0 0x1000>;
|
|
||||||
interrupts = <19 4>;
|
|
||||||
interrupt-parent = <&plic0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
mmc0: mmc@f0e00000 {
|
|
||||||
compatible = "andestech,atfsdc010";
|
|
||||||
max-frequency = <100000000>;
|
|
||||||
clock-freq-min-max = <400000 100000000>;
|
|
||||||
fifo-depth = <0x10>;
|
|
||||||
reg = <0x0 0xf0e00000 0x0 0x1000>;
|
|
||||||
interrupts = <18 4>;
|
|
||||||
cap-sd-highspeed;
|
|
||||||
interrupt-parent = <&plic0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
dma0: dma@f0c00000 {
|
|
||||||
compatible = "andestech,atcdmac300";
|
|
||||||
reg = <0x0 0xf0c00000 0x0 0x1000>;
|
|
||||||
interrupts = <10 4 64 4 65 4 66 4 67 4 68 4 69 4 70 4 71 4>;
|
|
||||||
dma-channels = <8>;
|
|
||||||
interrupt-parent = <&plic0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
lcd0: lcd@e0200000 {
|
|
||||||
compatible = "andestech,atflcdc100";
|
|
||||||
reg = <0x0 0xe0200000 0x0 0x1000>;
|
|
||||||
interrupts = <20 4>;
|
|
||||||
interrupt-parent = <&plic0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
smc0: smc@e0400000 {
|
|
||||||
compatible = "andestech,atfsmc020";
|
|
||||||
reg = <0x0 0xe0400000 0x0 0x1000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
snd0: snd@f0d00000 {
|
|
||||||
compatible = "andestech,atfac97";
|
|
||||||
reg = <0x0 0xf0d00000 0x0 0x1000>;
|
|
||||||
interrupts = <17 4>;
|
|
||||||
interrupt-parent = <&plic0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtio_mmio@fe007000 {
|
|
||||||
interrupts = <0x17 0x4>;
|
|
||||||
interrupt-parent = <0x2>;
|
|
||||||
reg = <0x0 0xfe007000 0x0 0x1000>;
|
|
||||||
compatible = "virtio,mmio";
|
|
||||||
};
|
|
||||||
|
|
||||||
virtio_mmio@fe006000 {
|
|
||||||
interrupts = <0x16 0x4>;
|
|
||||||
interrupt-parent = <0x2>;
|
|
||||||
reg = <0x0 0xfe006000 0x0 0x1000>;
|
|
||||||
compatible = "virtio,mmio";
|
|
||||||
};
|
|
||||||
|
|
||||||
virtio_mmio@fe005000 {
|
|
||||||
interrupts = <0x15 0x4>;
|
|
||||||
interrupt-parent = <0x2>;
|
|
||||||
reg = <0x0 0xfe005000 0x0 0x1000>;
|
|
||||||
compatible = "virtio,mmio";
|
|
||||||
};
|
|
||||||
|
|
||||||
virtio_mmio@fe004000 {
|
|
||||||
interrupts = <0x14 0x4>;
|
|
||||||
interrupt-parent = <0x2>;
|
|
||||||
reg = <0x0 0xfe004000 0x0 0x1000>;
|
|
||||||
compatible = "virtio,mmio";
|
|
||||||
};
|
|
||||||
|
|
||||||
virtio_mmio@fe003000 {
|
|
||||||
interrupts = <0x13 0x4>;
|
|
||||||
interrupt-parent = <0x2>;
|
|
||||||
reg = <0x0 0xfe003000 0x0 0x1000>;
|
|
||||||
compatible = "virtio,mmio";
|
|
||||||
};
|
|
||||||
|
|
||||||
virtio_mmio@fe002000 {
|
|
||||||
interrupts = <0x12 0x4>;
|
|
||||||
interrupt-parent = <0x2>;
|
|
||||||
reg = <0x0 0xfe002000 0x0 0x1000>;
|
|
||||||
compatible = "virtio,mmio";
|
|
||||||
};
|
|
||||||
|
|
||||||
virtio_mmio@fe001000 {
|
|
||||||
interrupts = <0x11 0x4>;
|
|
||||||
interrupt-parent = <0x2>;
|
|
||||||
reg = <0x0 0xfe001000 0x0 0x1000>;
|
|
||||||
compatible = "virtio,mmio";
|
|
||||||
};
|
|
||||||
|
|
||||||
virtio_mmio@fe000000 {
|
|
||||||
interrupts = <0x10 0x4>;
|
|
||||||
interrupt-parent = <0x2>;
|
|
||||||
reg = <0x0 0xfe000000 0x0 0x1000>;
|
|
||||||
compatible = "virtio,mmio";
|
|
||||||
};
|
|
||||||
|
|
||||||
nor@0,0 {
|
|
||||||
compatible = "cfi-flash";
|
|
||||||
reg = <0x0 0x88000000 0x0 0x1000>;
|
|
||||||
bank-width = <2>;
|
|
||||||
device-width = <1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
spi: spi@f0b00000 {
|
|
||||||
compatible = "andestech,atcspi200";
|
|
||||||
reg = <0x0 0xf0b00000 0x0 0x1000>;
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
num-cs = <1>;
|
|
||||||
clocks = <&spiclk>;
|
|
||||||
interrupts = <4 4>;
|
|
||||||
interrupt-parent = <&plic0>;
|
|
||||||
flash@0 {
|
|
||||||
compatible = "spi-flash";
|
|
||||||
spi-max-frequency = <50000000>;
|
|
||||||
reg = <0>;
|
|
||||||
spi-cpol;
|
|
||||||
spi-cpha;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -61,10 +61,12 @@
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#define xcsr(csr) #csr
|
||||||
|
|
||||||
#define csr_swap(csr, val) \
|
#define csr_swap(csr, val) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (unsigned long)(val); \
|
unsigned long __v = (unsigned long)(val); \
|
||||||
__asm__ __volatile__ ("csrrw %0, " #csr ", %1" \
|
__asm__ __volatile__ ("csrrw %0, " xcsr(csr) ", %1" \
|
||||||
: "=r" (__v) : "rK" (__v) \
|
: "=r" (__v) : "rK" (__v) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
__v; \
|
__v; \
|
||||||
|
@ -73,7 +75,7 @@
|
||||||
#define csr_read(csr) \
|
#define csr_read(csr) \
|
||||||
({ \
|
({ \
|
||||||
register unsigned long __v; \
|
register unsigned long __v; \
|
||||||
__asm__ __volatile__ ("csrr %0, " #csr \
|
__asm__ __volatile__ ("csrr %0, " xcsr(csr) \
|
||||||
: "=r" (__v) : \
|
: "=r" (__v) : \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
__v; \
|
__v; \
|
||||||
|
@ -82,7 +84,7 @@
|
||||||
#define csr_write(csr, val) \
|
#define csr_write(csr, val) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (unsigned long)(val); \
|
unsigned long __v = (unsigned long)(val); \
|
||||||
__asm__ __volatile__ ("csrw " #csr ", %0" \
|
__asm__ __volatile__ ("csrw " xcsr(csr) ", %0" \
|
||||||
: : "rK" (__v) \
|
: : "rK" (__v) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
})
|
})
|
||||||
|
@ -90,7 +92,7 @@
|
||||||
#define csr_read_set(csr, val) \
|
#define csr_read_set(csr, val) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (unsigned long)(val); \
|
unsigned long __v = (unsigned long)(val); \
|
||||||
__asm__ __volatile__ ("csrrs %0, " #csr ", %1" \
|
__asm__ __volatile__ ("csrrs %0, " xcsr(csr) ", %1" \
|
||||||
: "=r" (__v) : "rK" (__v) \
|
: "=r" (__v) : "rK" (__v) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
__v; \
|
__v; \
|
||||||
|
@ -99,7 +101,7 @@
|
||||||
#define csr_set(csr, val) \
|
#define csr_set(csr, val) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (unsigned long)(val); \
|
unsigned long __v = (unsigned long)(val); \
|
||||||
__asm__ __volatile__ ("csrs " #csr ", %0" \
|
__asm__ __volatile__ ("csrs " xcsr(csr) ", %0" \
|
||||||
: : "rK" (__v) \
|
: : "rK" (__v) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
})
|
})
|
||||||
|
@ -107,7 +109,7 @@
|
||||||
#define csr_read_clear(csr, val) \
|
#define csr_read_clear(csr, val) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (unsigned long)(val); \
|
unsigned long __v = (unsigned long)(val); \
|
||||||
__asm__ __volatile__ ("csrrc %0, " #csr ", %1" \
|
__asm__ __volatile__ ("csrrc %0, " xcsr(csr) ", %1" \
|
||||||
: "=r" (__v) : "rK" (__v) \
|
: "=r" (__v) : "rK" (__v) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
__v; \
|
__v; \
|
||||||
|
@ -116,7 +118,7 @@
|
||||||
#define csr_clear(csr, val) \
|
#define csr_clear(csr, val) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (unsigned long)(val); \
|
unsigned long __v = (unsigned long)(val); \
|
||||||
__asm__ __volatile__ ("csrc " #csr ", %0" \
|
__asm__ __volatile__ ("csrc " xcsr(csr) ", %0" \
|
||||||
: : "rK" (__v) \
|
: : "rK" (__v) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
})
|
})
|
||||||
|
|
|
@ -85,6 +85,21 @@
|
||||||
#define IRQ_COP 12
|
#define IRQ_COP 12
|
||||||
#define IRQ_HOST 13
|
#define IRQ_HOST 13
|
||||||
|
|
||||||
|
#define CAUSE_MISALIGNED_FETCH 0
|
||||||
|
#define CAUSE_FETCH_ACCESS 1
|
||||||
|
#define CAUSE_ILLEGAL_INSTRUCTION 2
|
||||||
|
#define CAUSE_BREAKPOINT 3
|
||||||
|
#define CAUSE_MISALIGNED_LOAD 4
|
||||||
|
#define CAUSE_LOAD_ACCESS 5
|
||||||
|
#define CAUSE_MISALIGNED_STORE 6
|
||||||
|
#define CAUSE_STORE_ACCESS 7
|
||||||
|
#define CAUSE_USER_ECALL 8
|
||||||
|
#define CAUSE_SUPERVISOR_ECALL 9
|
||||||
|
#define CAUSE_MACHINE_ECALL 11
|
||||||
|
#define CAUSE_FETCH_PAGE_FAULT 12
|
||||||
|
#define CAUSE_LOAD_PAGE_FAULT 13
|
||||||
|
#define CAUSE_STORE_PAGE_FAULT 15
|
||||||
|
|
||||||
#define DEFAULT_RSTVEC 0x00001000
|
#define DEFAULT_RSTVEC 0x00001000
|
||||||
#define DEFAULT_NMIVEC 0x00001004
|
#define DEFAULT_NMIVEC 0x00001004
|
||||||
#define DEFAULT_MTVEC 0x00001010
|
#define DEFAULT_MTVEC 0x00001010
|
||||||
|
@ -152,6 +167,227 @@
|
||||||
#define RISCV_PGSHIFT 12
|
#define RISCV_PGSHIFT 12
|
||||||
#define RISCV_PGSIZE BIT(RISCV_PGSHIFT)
|
#define RISCV_PGSIZE BIT(RISCV_PGSHIFT)
|
||||||
|
|
||||||
|
/* CSR numbers */
|
||||||
|
#define CSR_FFLAGS 0x1
|
||||||
|
#define CSR_FRM 0x2
|
||||||
|
#define CSR_FCSR 0x3
|
||||||
|
|
||||||
|
#define CSR_SSTATUS 0x100
|
||||||
|
#define CSR_SEDELEG 0x102
|
||||||
|
#define CSR_SIDELEG 0x103
|
||||||
|
#define CSR_SIE 0x104
|
||||||
|
#define CSR_STVEC 0x105
|
||||||
|
#define CSR_SCOUNTEREN 0x106
|
||||||
|
#define CSR_SSCRATCH 0x140
|
||||||
|
#define CSR_SEPC 0x141
|
||||||
|
#define CSR_SCAUSE 0x142
|
||||||
|
#define CSR_STVAL 0x143
|
||||||
|
#define CSR_SIP 0x144
|
||||||
|
#define CSR_SATP 0x180
|
||||||
|
|
||||||
|
#define CSR_MSTATUS 0x300
|
||||||
|
#define CSR_MISA 0x301
|
||||||
|
#define CSR_MEDELEG 0x302
|
||||||
|
#define CSR_MIDELEG 0x303
|
||||||
|
#define CSR_MIE 0x304
|
||||||
|
#define CSR_MTVEC 0x305
|
||||||
|
#define CSR_MCOUNTEREN 0x306
|
||||||
|
#define CSR_MHPMEVENT3 0x323
|
||||||
|
#define CSR_MHPMEVENT4 0x324
|
||||||
|
#define CSR_MHPMEVENT5 0x325
|
||||||
|
#define CSR_MHPMEVENT6 0x326
|
||||||
|
#define CSR_MHPMEVENT7 0x327
|
||||||
|
#define CSR_MHPMEVENT8 0x328
|
||||||
|
#define CSR_MHPMEVENT9 0x329
|
||||||
|
#define CSR_MHPMEVENT10 0x32a
|
||||||
|
#define CSR_MHPMEVENT11 0x32b
|
||||||
|
#define CSR_MHPMEVENT12 0x32c
|
||||||
|
#define CSR_MHPMEVENT13 0x32d
|
||||||
|
#define CSR_MHPMEVENT14 0x32e
|
||||||
|
#define CSR_MHPMEVENT15 0x32f
|
||||||
|
#define CSR_MHPMEVENT16 0x330
|
||||||
|
#define CSR_MHPMEVENT17 0x331
|
||||||
|
#define CSR_MHPMEVENT18 0x332
|
||||||
|
#define CSR_MHPMEVENT19 0x333
|
||||||
|
#define CSR_MHPMEVENT20 0x334
|
||||||
|
#define CSR_MHPMEVENT21 0x335
|
||||||
|
#define CSR_MHPMEVENT22 0x336
|
||||||
|
#define CSR_MHPMEVENT23 0x337
|
||||||
|
#define CSR_MHPMEVENT24 0x338
|
||||||
|
#define CSR_MHPMEVENT25 0x339
|
||||||
|
#define CSR_MHPMEVENT26 0x33a
|
||||||
|
#define CSR_MHPMEVENT27 0x33b
|
||||||
|
#define CSR_MHPMEVENT28 0x33c
|
||||||
|
#define CSR_MHPMEVENT29 0x33d
|
||||||
|
#define CSR_MHPMEVENT30 0x33e
|
||||||
|
#define CSR_MHPMEVENT31 0x33f
|
||||||
|
#define CSR_MSCRATCH 0x340
|
||||||
|
#define CSR_MEPC 0x341
|
||||||
|
#define CSR_MCAUSE 0x342
|
||||||
|
#define CSR_MTVAL 0x343
|
||||||
|
#define CSR_MIP 0x344
|
||||||
|
#define CSR_PMPCFG0 0x3a0
|
||||||
|
#define CSR_PMPCFG1 0x3a1
|
||||||
|
#define CSR_PMPCFG2 0x3a2
|
||||||
|
#define CSR_PMPCFG3 0x3a3
|
||||||
|
#define CSR_PMPADDR0 0x3b0
|
||||||
|
#define CSR_PMPADDR1 0x3b1
|
||||||
|
#define CSR_PMPADDR2 0x3b2
|
||||||
|
#define CSR_PMPADDR3 0x3b3
|
||||||
|
#define CSR_PMPADDR4 0x3b4
|
||||||
|
#define CSR_PMPADDR5 0x3b5
|
||||||
|
#define CSR_PMPADDR6 0x3b6
|
||||||
|
#define CSR_PMPADDR7 0x3b7
|
||||||
|
#define CSR_PMPADDR8 0x3b8
|
||||||
|
#define CSR_PMPADDR9 0x3b9
|
||||||
|
#define CSR_PMPADDR10 0x3ba
|
||||||
|
#define CSR_PMPADDR11 0x3bb
|
||||||
|
#define CSR_PMPADDR12 0x3bc
|
||||||
|
#define CSR_PMPADDR13 0x3bd
|
||||||
|
#define CSR_PMPADDR14 0x3be
|
||||||
|
#define CSR_PMPADDR15 0x3bf
|
||||||
|
|
||||||
|
#define CSR_TSELECT 0x7a0
|
||||||
|
#define CSR_TDATA1 0x7a1
|
||||||
|
#define CSR_TDATA2 0x7a2
|
||||||
|
#define CSR_TDATA3 0x7a3
|
||||||
|
#define CSR_DCSR 0x7b0
|
||||||
|
#define CSR_DPC 0x7b1
|
||||||
|
#define CSR_DSCRATCH 0x7b2
|
||||||
|
|
||||||
|
#define CSR_MCYCLE 0xb00
|
||||||
|
#define CSR_MINSTRET 0xb02
|
||||||
|
#define CSR_MHPMCOUNTER3 0xb03
|
||||||
|
#define CSR_MHPMCOUNTER4 0xb04
|
||||||
|
#define CSR_MHPMCOUNTER5 0xb05
|
||||||
|
#define CSR_MHPMCOUNTER6 0xb06
|
||||||
|
#define CSR_MHPMCOUNTER7 0xb07
|
||||||
|
#define CSR_MHPMCOUNTER8 0xb08
|
||||||
|
#define CSR_MHPMCOUNTER9 0xb09
|
||||||
|
#define CSR_MHPMCOUNTER10 0xb0a
|
||||||
|
#define CSR_MHPMCOUNTER11 0xb0b
|
||||||
|
#define CSR_MHPMCOUNTER12 0xb0c
|
||||||
|
#define CSR_MHPMCOUNTER13 0xb0d
|
||||||
|
#define CSR_MHPMCOUNTER14 0xb0e
|
||||||
|
#define CSR_MHPMCOUNTER15 0xb0f
|
||||||
|
#define CSR_MHPMCOUNTER16 0xb10
|
||||||
|
#define CSR_MHPMCOUNTER17 0xb11
|
||||||
|
#define CSR_MHPMCOUNTER18 0xb12
|
||||||
|
#define CSR_MHPMCOUNTER19 0xb13
|
||||||
|
#define CSR_MHPMCOUNTER20 0xb14
|
||||||
|
#define CSR_MHPMCOUNTER21 0xb15
|
||||||
|
#define CSR_MHPMCOUNTER22 0xb16
|
||||||
|
#define CSR_MHPMCOUNTER23 0xb17
|
||||||
|
#define CSR_MHPMCOUNTER24 0xb18
|
||||||
|
#define CSR_MHPMCOUNTER25 0xb19
|
||||||
|
#define CSR_MHPMCOUNTER26 0xb1a
|
||||||
|
#define CSR_MHPMCOUNTER27 0xb1b
|
||||||
|
#define CSR_MHPMCOUNTER28 0xb1c
|
||||||
|
#define CSR_MHPMCOUNTER29 0xb1d
|
||||||
|
#define CSR_MHPMCOUNTER30 0xb1e
|
||||||
|
#define CSR_MHPMCOUNTER31 0xb1f
|
||||||
|
#define CSR_MCYCLEH 0xb80
|
||||||
|
#define CSR_MINSTRETH 0xb82
|
||||||
|
#define CSR_MHPMCOUNTER3H 0xb83
|
||||||
|
#define CSR_MHPMCOUNTER4H 0xb84
|
||||||
|
#define CSR_MHPMCOUNTER5H 0xb85
|
||||||
|
#define CSR_MHPMCOUNTER6H 0xb86
|
||||||
|
#define CSR_MHPMCOUNTER7H 0xb87
|
||||||
|
#define CSR_MHPMCOUNTER8H 0xb88
|
||||||
|
#define CSR_MHPMCOUNTER9H 0xb89
|
||||||
|
#define CSR_MHPMCOUNTER10H 0xb8a
|
||||||
|
#define CSR_MHPMCOUNTER11H 0xb8b
|
||||||
|
#define CSR_MHPMCOUNTER12H 0xb8c
|
||||||
|
#define CSR_MHPMCOUNTER13H 0xb8d
|
||||||
|
#define CSR_MHPMCOUNTER14H 0xb8e
|
||||||
|
#define CSR_MHPMCOUNTER15H 0xb8f
|
||||||
|
#define CSR_MHPMCOUNTER16H 0xb90
|
||||||
|
#define CSR_MHPMCOUNTER17H 0xb91
|
||||||
|
#define CSR_MHPMCOUNTER18H 0xb92
|
||||||
|
#define CSR_MHPMCOUNTER19H 0xb93
|
||||||
|
#define CSR_MHPMCOUNTER20H 0xb94
|
||||||
|
#define CSR_MHPMCOUNTER21H 0xb95
|
||||||
|
#define CSR_MHPMCOUNTER22H 0xb96
|
||||||
|
#define CSR_MHPMCOUNTER23H 0xb97
|
||||||
|
#define CSR_MHPMCOUNTER24H 0xb98
|
||||||
|
#define CSR_MHPMCOUNTER25H 0xb99
|
||||||
|
#define CSR_MHPMCOUNTER26H 0xb9a
|
||||||
|
#define CSR_MHPMCOUNTER27H 0xb9b
|
||||||
|
#define CSR_MHPMCOUNTER28H 0xb9c
|
||||||
|
#define CSR_MHPMCOUNTER29H 0xb9d
|
||||||
|
#define CSR_MHPMCOUNTER30H 0xb9e
|
||||||
|
#define CSR_MHPMCOUNTER31H 0xb9f
|
||||||
|
|
||||||
|
#define CSR_CYCLE 0xc00
|
||||||
|
#define CSR_TIME 0xc01
|
||||||
|
#define CSR_INSTRET 0xc02
|
||||||
|
#define CSR_HPMCOUNTER3 0xc03
|
||||||
|
#define CSR_HPMCOUNTER4 0xc04
|
||||||
|
#define CSR_HPMCOUNTER5 0xc05
|
||||||
|
#define CSR_HPMCOUNTER6 0xc06
|
||||||
|
#define CSR_HPMCOUNTER7 0xc07
|
||||||
|
#define CSR_HPMCOUNTER8 0xc08
|
||||||
|
#define CSR_HPMCOUNTER9 0xc09
|
||||||
|
#define CSR_HPMCOUNTER10 0xc0a
|
||||||
|
#define CSR_HPMCOUNTER11 0xc0b
|
||||||
|
#define CSR_HPMCOUNTER12 0xc0c
|
||||||
|
#define CSR_HPMCOUNTER13 0xc0d
|
||||||
|
#define CSR_HPMCOUNTER14 0xc0e
|
||||||
|
#define CSR_HPMCOUNTER15 0xc0f
|
||||||
|
#define CSR_HPMCOUNTER16 0xc10
|
||||||
|
#define CSR_HPMCOUNTER17 0xc11
|
||||||
|
#define CSR_HPMCOUNTER18 0xc12
|
||||||
|
#define CSR_HPMCOUNTER19 0xc13
|
||||||
|
#define CSR_HPMCOUNTER20 0xc14
|
||||||
|
#define CSR_HPMCOUNTER21 0xc15
|
||||||
|
#define CSR_HPMCOUNTER22 0xc16
|
||||||
|
#define CSR_HPMCOUNTER23 0xc17
|
||||||
|
#define CSR_HPMCOUNTER24 0xc18
|
||||||
|
#define CSR_HPMCOUNTER25 0xc19
|
||||||
|
#define CSR_HPMCOUNTER26 0xc1a
|
||||||
|
#define CSR_HPMCOUNTER27 0xc1b
|
||||||
|
#define CSR_HPMCOUNTER28 0xc1c
|
||||||
|
#define CSR_HPMCOUNTER29 0xc1d
|
||||||
|
#define CSR_HPMCOUNTER30 0xc1e
|
||||||
|
#define CSR_HPMCOUNTER31 0xc1f
|
||||||
|
#define CSR_CYCLEH 0xc80
|
||||||
|
#define CSR_TIMEH 0xc81
|
||||||
|
#define CSR_INSTRETH 0xc82
|
||||||
|
#define CSR_HPMCOUNTER3H 0xc83
|
||||||
|
#define CSR_HPMCOUNTER4H 0xc84
|
||||||
|
#define CSR_HPMCOUNTER5H 0xc85
|
||||||
|
#define CSR_HPMCOUNTER6H 0xc86
|
||||||
|
#define CSR_HPMCOUNTER7H 0xc87
|
||||||
|
#define CSR_HPMCOUNTER8H 0xc88
|
||||||
|
#define CSR_HPMCOUNTER9H 0xc89
|
||||||
|
#define CSR_HPMCOUNTER10H 0xc8a
|
||||||
|
#define CSR_HPMCOUNTER11H 0xc8b
|
||||||
|
#define CSR_HPMCOUNTER12H 0xc8c
|
||||||
|
#define CSR_HPMCOUNTER13H 0xc8d
|
||||||
|
#define CSR_HPMCOUNTER14H 0xc8e
|
||||||
|
#define CSR_HPMCOUNTER15H 0xc8f
|
||||||
|
#define CSR_HPMCOUNTER16H 0xc90
|
||||||
|
#define CSR_HPMCOUNTER17H 0xc91
|
||||||
|
#define CSR_HPMCOUNTER18H 0xc92
|
||||||
|
#define CSR_HPMCOUNTER19H 0xc93
|
||||||
|
#define CSR_HPMCOUNTER20H 0xc94
|
||||||
|
#define CSR_HPMCOUNTER21H 0xc95
|
||||||
|
#define CSR_HPMCOUNTER22H 0xc96
|
||||||
|
#define CSR_HPMCOUNTER23H 0xc97
|
||||||
|
#define CSR_HPMCOUNTER24H 0xc98
|
||||||
|
#define CSR_HPMCOUNTER25H 0xc99
|
||||||
|
#define CSR_HPMCOUNTER26H 0xc9a
|
||||||
|
#define CSR_HPMCOUNTER27H 0xc9b
|
||||||
|
#define CSR_HPMCOUNTER28H 0xc9c
|
||||||
|
#define CSR_HPMCOUNTER29H 0xc9d
|
||||||
|
#define CSR_HPMCOUNTER30H 0xc9e
|
||||||
|
#define CSR_HPMCOUNTER31H 0xc9f
|
||||||
|
|
||||||
|
#define CSR_MVENDORID 0xf11
|
||||||
|
#define CSR_MARCHID 0xf12
|
||||||
|
#define CSR_MIMPID 0xf13
|
||||||
|
#define CSR_MHARTID 0xf14
|
||||||
|
|
||||||
#endif /* __riscv */
|
#endif /* __riscv */
|
||||||
|
|
||||||
#endif /* RISCV_CSR_ENCODING_H */
|
#endif /* RISCV_CSR_ENCODING_H */
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
|
|
||||||
/* Architecture-specific global data */
|
/* Architecture-specific global data */
|
||||||
struct arch_global_data {
|
struct arch_global_data {
|
||||||
|
long boot_hart; /* boot hart id */
|
||||||
|
#ifdef CONFIG_SIFIVE_CLINT
|
||||||
|
void __iomem *clint; /* clint base address */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <asm-generic/global_data.h>
|
#include <asm-generic/global_data.h>
|
||||||
|
|
19
arch/riscv/include/asm/syscon.h
Normal file
19
arch/riscv/include/asm/syscon.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_SYSCON_H
|
||||||
|
#define _ASM_SYSCON_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System controllers in a RISC-V system
|
||||||
|
*
|
||||||
|
* So far only SiFive's Core Local Interruptor (CLINT) is defined.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
RISCV_NONE,
|
||||||
|
RISCV_SYSCON_CLINT, /* Core Local Interruptor (CLINT) */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _ASM_SYSCON_H */
|
|
@ -9,6 +9,8 @@
|
||||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||||
obj-$(CONFIG_CMD_GO) += boot.o
|
obj-$(CONFIG_CMD_GO) += boot.o
|
||||||
obj-y += cache.o
|
obj-y += cache.o
|
||||||
|
obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
|
||||||
|
obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
|
||||||
obj-y += interrupts.o
|
obj-y += interrupts.o
|
||||||
obj-y += reset.o
|
obj-y += reset.o
|
||||||
obj-y += setjmp.o
|
obj-y += setjmp.o
|
||||||
|
|
19
arch/riscv/lib/asm-offsets.c
Normal file
19
arch/riscv/lib/asm-offsets.c
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*
|
||||||
|
* From arch/x86/lib/asm-offsets.c
|
||||||
|
*
|
||||||
|
* This program is used to generate definitions needed by
|
||||||
|
* assembly language modules.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <linux/kbuild.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -93,7 +93,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
|
||||||
|
|
||||||
if (!fake) {
|
if (!fake) {
|
||||||
if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
|
if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
|
||||||
kernel(csr_read(mhartid), images->ft_addr);
|
kernel(gd->arch.boot_hart, images->ft_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,36 @@
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/encoding.h>
|
#include <asm/encoding.h>
|
||||||
|
|
||||||
static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs);
|
static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
static const char * const exception_code[] = {
|
||||||
|
"Instruction address misaligned",
|
||||||
|
"Instruction access fault",
|
||||||
|
"Illegal instruction",
|
||||||
|
"Breakpoint",
|
||||||
|
"Load address misaligned",
|
||||||
|
"Load access fault",
|
||||||
|
"Store/AMO address misaligned",
|
||||||
|
"Store/AMO access fault",
|
||||||
|
"Environment call from U-mode",
|
||||||
|
"Environment call from S-mode",
|
||||||
|
"Reserved",
|
||||||
|
"Environment call from M-mode",
|
||||||
|
"Instruction page fault",
|
||||||
|
"Load page fault",
|
||||||
|
"Reserved",
|
||||||
|
"Store/AMO page fault",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (code < ARRAY_SIZE(exception_code)) {
|
||||||
|
printf("exception code: %ld , %s , epc %lx , ra %lx\n",
|
||||||
|
code, exception_code[code], epc, regs->ra);
|
||||||
|
} else {
|
||||||
|
printf("Reserved\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
hang();
|
||||||
|
}
|
||||||
|
|
||||||
int interrupt_init(void)
|
int interrupt_init(void)
|
||||||
{
|
{
|
||||||
|
@ -72,34 +101,3 @@ __attribute__((weak)) void external_interrupt(struct pt_regs *regs)
|
||||||
__attribute__((weak)) void timer_interrupt(struct pt_regs *regs)
|
__attribute__((weak)) void timer_interrupt(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
static const char * const exception_code[] = {
|
|
||||||
"Instruction address misaligned",
|
|
||||||
"Instruction access fault",
|
|
||||||
"Illegal instruction",
|
|
||||||
"Breakpoint",
|
|
||||||
"Load address misaligned",
|
|
||||||
"Load access fault",
|
|
||||||
"Store/AMO address misaligned",
|
|
||||||
"Store/AMO access fault",
|
|
||||||
"Environment call from U-mode",
|
|
||||||
"Environment call from S-mode",
|
|
||||||
"Reserved",
|
|
||||||
"Environment call from M-mode",
|
|
||||||
"Instruction page fault",
|
|
||||||
"Load page fault",
|
|
||||||
"Reserved",
|
|
||||||
"Store/AMO page fault",
|
|
||||||
};
|
|
||||||
|
|
||||||
if (code < ARRAY_SIZE(exception_code)) {
|
|
||||||
printf("exception code: %ld , %s , epc %lx , ra %lx\n",
|
|
||||||
code, exception_code[code], epc, regs->ra);
|
|
||||||
} else {
|
|
||||||
printf("Reserved\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
hang();
|
|
||||||
}
|
|
||||||
|
|
38
arch/riscv/lib/rdtime.c
Normal file
38
arch/riscv/lib/rdtime.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018, Anup Patel <anup@brainfault.org>
|
||||||
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*
|
||||||
|
* The riscv_get_time() API implementation that is using the
|
||||||
|
* standard rdtime instruction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
|
/* Implement the API required by RISC-V timer driver */
|
||||||
|
int riscv_get_time(u64 *time)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
u64 n;
|
||||||
|
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"rdtime %0"
|
||||||
|
: "=r" (n));
|
||||||
|
|
||||||
|
*time = n;
|
||||||
|
#else
|
||||||
|
u32 lo, hi, tmp;
|
||||||
|
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"1:\n"
|
||||||
|
"rdtimeh %0\n"
|
||||||
|
"rdtime %1\n"
|
||||||
|
"rdtimeh %2\n"
|
||||||
|
"bne %0, %2, 1b"
|
||||||
|
: "=&r" (hi), "=&r" (lo), "=&r" (tmp));
|
||||||
|
|
||||||
|
*time = ((u64)hi << 32) | lo;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
84
arch/riscv/lib/sifive_clint.c
Normal file
84
arch/riscv/lib/sifive_clint.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*
|
||||||
|
* U-Boot syscon driver for SiFive's Core Local Interruptor (CLINT).
|
||||||
|
* The CLINT block holds memory-mapped control and status registers
|
||||||
|
* associated with software and timer interrupts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <regmap.h>
|
||||||
|
#include <syscon.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/syscon.h>
|
||||||
|
|
||||||
|
/* MSIP registers */
|
||||||
|
#define MSIP_REG(base, hart) ((ulong)(base) + (hart) * 4)
|
||||||
|
/* mtime compare register */
|
||||||
|
#define MTIMECMP_REG(base, hart) ((ulong)(base) + 0x4000 + (hart) * 8)
|
||||||
|
/* mtime register */
|
||||||
|
#define MTIME_REG(base) ((ulong)(base) + 0xbff8)
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
#define CLINT_BASE_GET(void) \
|
||||||
|
do { \
|
||||||
|
long *ret; \
|
||||||
|
\
|
||||||
|
if (!gd->arch.clint) { \
|
||||||
|
ret = syscon_get_first_range(RISCV_SYSCON_CLINT); \
|
||||||
|
if (IS_ERR(ret)) \
|
||||||
|
return PTR_ERR(ret); \
|
||||||
|
gd->arch.clint = ret; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
int riscv_get_time(u64 *time)
|
||||||
|
{
|
||||||
|
CLINT_BASE_GET();
|
||||||
|
|
||||||
|
*time = readq((void __iomem *)MTIME_REG(gd->arch.clint));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int riscv_set_timecmp(int hart, u64 cmp)
|
||||||
|
{
|
||||||
|
CLINT_BASE_GET();
|
||||||
|
|
||||||
|
writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int riscv_send_ipi(int hart)
|
||||||
|
{
|
||||||
|
CLINT_BASE_GET();
|
||||||
|
|
||||||
|
writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int riscv_clear_ipi(int hart)
|
||||||
|
{
|
||||||
|
CLINT_BASE_GET();
|
||||||
|
|
||||||
|
writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct udevice_id sifive_clint_ids[] = {
|
||||||
|
{ .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(sifive_clint) = {
|
||||||
|
.name = "sifive_clint",
|
||||||
|
.id = UCLASS_SYSCON,
|
||||||
|
.of_match = sifive_clint_ids,
|
||||||
|
.flags = DM_FLAG_PRE_RELOC,
|
||||||
|
};
|
|
@ -21,4 +21,8 @@ config ENV_SIZE
|
||||||
config ENV_OFFSET
|
config ENV_OFFSET
|
||||||
default 0x140000 if ENV_IS_IN_SPI_FLASH
|
default 0x140000 if ENV_IS_IN_SPI_FLASH
|
||||||
|
|
||||||
|
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||||
|
def_bool y
|
||||||
|
select RISCV_NDS
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -3,6 +3,5 @@ M: Rick Chen <rick@andestech.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: board/AndesTech/ax25-ae350/
|
F: board/AndesTech/ax25-ae350/
|
||||||
F: include/configs/ax25-ae350.h
|
F: include/configs/ax25-ae350.h
|
||||||
F: configs/a25-ae350_32_defconfig
|
F: configs/ae350_rv32_defconfig
|
||||||
F: configs/ax25-ae350_64_defconfig
|
F: configs/ae350_rv64_defconfig
|
||||||
F: configs/ax25-ae350_defconfig
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ config SYS_TEXT_BASE
|
||||||
|
|
||||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||||
def_bool y
|
def_bool y
|
||||||
|
select QEMU_RISCV
|
||||||
imply SYS_NS16550
|
imply SYS_NS16550
|
||||||
imply VIRTIO_MMIO
|
imply VIRTIO_MMIO
|
||||||
imply VIRTIO_NET
|
imply VIRTIO_NET
|
||||||
|
@ -32,5 +33,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
|
||||||
imply CMD_FAT
|
imply CMD_FAT
|
||||||
imply BOARD_LATE_INIT
|
imply BOARD_LATE_INIT
|
||||||
imply OF_BOARD_SETUP
|
imply OF_BOARD_SETUP
|
||||||
|
imply SIFIVE_SERIAL
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -25,7 +25,7 @@ Build and boot steps
|
||||||
|
|
||||||
build:
|
build:
|
||||||
1. Prepare the toolchains and make sure the $PATH to toolchains is correct.
|
1. Prepare the toolchains and make sure the $PATH to toolchains is correct.
|
||||||
2. Use `make ax25-ae350_defconfig` in u-boot root to build the image.
|
2. Use `make ae350_rv[32|64]_defconfig` in u-boot root to build the image for 32 or 64 bit.
|
||||||
|
|
||||||
Verification
|
Verification
|
||||||
====================
|
====================
|
||||||
|
|
|
@ -13,3 +13,9 @@ config CPU_MPC83XX
|
||||||
select CLK_MPC83XX
|
select CLK_MPC83XX
|
||||||
help
|
help
|
||||||
Support CPU cores for SoCs of the MPC83xx series.
|
Support CPU cores for SoCs of the MPC83xx series.
|
||||||
|
|
||||||
|
config CPU_RISCV
|
||||||
|
bool "Enable RISC-V CPU driver"
|
||||||
|
depends on CPU && RISCV
|
||||||
|
help
|
||||||
|
Support CPU cores for RISC-V architecture.
|
||||||
|
|
|
@ -8,4 +8,5 @@ obj-$(CONFIG_CPU) += cpu-uclass.o
|
||||||
|
|
||||||
obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
|
obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
|
||||||
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
|
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
|
||||||
|
obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
|
||||||
obj-$(CONFIG_SANDBOX) += cpu_sandbox.o
|
obj-$(CONFIG_SANDBOX) += cpu_sandbox.o
|
||||||
|
|
116
drivers/cpu/riscv_cpu.c
Normal file
116
drivers/cpu/riscv_cpu.c
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <cpu.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dm/device-internal.h>
|
||||||
|
#include <dm/lists.h>
|
||||||
|
|
||||||
|
static int riscv_cpu_get_desc(struct udevice *dev, char *buf, int size)
|
||||||
|
{
|
||||||
|
const char *isa;
|
||||||
|
|
||||||
|
isa = dev_read_string(dev, "riscv,isa");
|
||||||
|
if (size < (strlen(isa) + 1))
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
|
strcpy(buf, isa);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info)
|
||||||
|
{
|
||||||
|
const char *mmu;
|
||||||
|
|
||||||
|
dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq);
|
||||||
|
|
||||||
|
mmu = dev_read_string(dev, "mmu-type");
|
||||||
|
if (!mmu)
|
||||||
|
info->features |= BIT(CPU_FEAT_MMU);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv_cpu_get_count(struct udevice *dev)
|
||||||
|
{
|
||||||
|
ofnode node;
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) {
|
||||||
|
const char *device_type;
|
||||||
|
|
||||||
|
device_type = ofnode_read_string(node, "device_type");
|
||||||
|
if (!device_type)
|
||||||
|
continue;
|
||||||
|
if (strcmp(device_type, "cpu") == 0)
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv_cpu_bind(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
|
||||||
|
struct driver *drv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* save the hart id */
|
||||||
|
plat->cpu_id = dev_read_addr(dev);
|
||||||
|
|
||||||
|
/* first examine the property in current cpu node */
|
||||||
|
ret = dev_read_u32(dev, "timebase-frequency", &plat->timebase_freq);
|
||||||
|
/* if not found, then look at the parent /cpus node */
|
||||||
|
if (ret)
|
||||||
|
dev_read_u32(dev->parent, "timebase-frequency",
|
||||||
|
&plat->timebase_freq);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bind riscv-timer driver on hart 0
|
||||||
|
*
|
||||||
|
* We only instantiate one timer device which is enough for U-Boot.
|
||||||
|
* Pass the "timebase-frequency" value as the driver data for the
|
||||||
|
* timer device.
|
||||||
|
*
|
||||||
|
* Return value is not checked since it's possible that the timer
|
||||||
|
* driver is not included.
|
||||||
|
*/
|
||||||
|
if (!plat->cpu_id && plat->timebase_freq) {
|
||||||
|
drv = lists_driver_lookup_name("riscv_timer");
|
||||||
|
if (!drv) {
|
||||||
|
debug("Cannot find the timer driver, not included?\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_bind_with_driver_data(dev, drv, "riscv_timer",
|
||||||
|
plat->timebase_freq, ofnode_null(),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct cpu_ops riscv_cpu_ops = {
|
||||||
|
.get_desc = riscv_cpu_get_desc,
|
||||||
|
.get_info = riscv_cpu_get_info,
|
||||||
|
.get_count = riscv_cpu_get_count,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id riscv_cpu_ids[] = {
|
||||||
|
{ .compatible = "riscv" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(riscv_cpu) = {
|
||||||
|
.name = "riscv_cpu",
|
||||||
|
.id = UCLASS_CPU,
|
||||||
|
.of_match = riscv_cpu_ids,
|
||||||
|
.bind = riscv_cpu_bind,
|
||||||
|
.ops = &riscv_cpu_ops,
|
||||||
|
.flags = DM_FLAG_PRE_RELOC,
|
||||||
|
};
|
|
@ -343,6 +343,13 @@ config DEBUG_UART_SANDBOX
|
||||||
start up driver model. The driver will be available until the real
|
start up driver model. The driver will be available until the real
|
||||||
driver model serial is running.
|
driver model serial is running.
|
||||||
|
|
||||||
|
config DEBUG_UART_SIFIVE
|
||||||
|
bool "SiFive UART"
|
||||||
|
help
|
||||||
|
Select this to enable a debug UART using the serial_sifive driver. You
|
||||||
|
will need to provide parameters to make this work. The driver will
|
||||||
|
be available until the real driver-model serial is running.
|
||||||
|
|
||||||
config DEBUG_UART_STM32
|
config DEBUG_UART_STM32
|
||||||
bool "STMicroelectronics STM32"
|
bool "STMicroelectronics STM32"
|
||||||
depends on STM32_SERIAL
|
depends on STM32_SERIAL
|
||||||
|
@ -679,6 +686,12 @@ 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 SIFIVE_SERIAL
|
||||||
|
bool "SiFive UART support"
|
||||||
|
depends on DM_SERIAL
|
||||||
|
help
|
||||||
|
This driver supports the SiFive UART. If unsure say N.
|
||||||
|
|
||||||
config STI_ASC_SERIAL
|
config STI_ASC_SERIAL
|
||||||
bool "STMicroelectronics on-chip UART"
|
bool "STMicroelectronics on-chip UART"
|
||||||
depends on DM_SERIAL && ARCH_STI
|
depends on DM_SERIAL && ARCH_STI
|
||||||
|
|
|
@ -67,6 +67,7 @@ obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o
|
||||||
obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
|
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_SIFIVE_SERIAL) += serial_sifive.o
|
||||||
|
|
||||||
ifndef CONFIG_SPL_BUILD
|
ifndef CONFIG_SPL_BUILD
|
||||||
obj-$(CONFIG_USB_TTY) += usbtty.o
|
obj-$(CONFIG_USB_TTY) += usbtty.o
|
||||||
|
|
215
drivers/serial/serial_sifive.c
Normal file
215
drivers/serial/serial_sifive.c
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Anup Patel <anup@brainfault.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <clk.h>
|
||||||
|
#include <common.h>
|
||||||
|
#include <debug_uart.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fdtdec.h>
|
||||||
|
#include <watchdog.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <linux/compiler.h>
|
||||||
|
#include <serial.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
#define UART_TXFIFO_FULL 0x80000000
|
||||||
|
#define UART_RXFIFO_EMPTY 0x80000000
|
||||||
|
#define UART_RXFIFO_DATA 0x000000ff
|
||||||
|
#define UART_TXCTRL_TXEN 0x1
|
||||||
|
#define UART_RXCTRL_RXEN 0x1
|
||||||
|
|
||||||
|
struct uart_sifive {
|
||||||
|
u32 txfifo;
|
||||||
|
u32 rxfifo;
|
||||||
|
u32 txctrl;
|
||||||
|
u32 rxctrl;
|
||||||
|
u32 ie;
|
||||||
|
u32 ip;
|
||||||
|
u32 div;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sifive_uart_platdata {
|
||||||
|
unsigned int clock;
|
||||||
|
int saved_input_char;
|
||||||
|
struct uart_sifive *regs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set up the baud rate in gd struct */
|
||||||
|
static void _sifive_serial_setbrg(struct uart_sifive *regs,
|
||||||
|
unsigned long clock, unsigned long baud)
|
||||||
|
{
|
||||||
|
writel((u32)((clock / baud) - 1), ®s->div);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _sifive_serial_init(struct uart_sifive *regs)
|
||||||
|
{
|
||||||
|
writel(UART_TXCTRL_TXEN, ®s->txctrl);
|
||||||
|
writel(UART_RXCTRL_RXEN, ®s->rxctrl);
|
||||||
|
writel(0, ®s->ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _sifive_serial_putc(struct uart_sifive *regs, const char c)
|
||||||
|
{
|
||||||
|
if (readl(®s->txfifo) & UART_TXFIFO_FULL)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
writel(c, ®s->txfifo);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _sifive_serial_getc(struct uart_sifive *regs)
|
||||||
|
{
|
||||||
|
int ch = readl(®s->rxfifo);
|
||||||
|
|
||||||
|
if (ch & UART_RXFIFO_EMPTY)
|
||||||
|
return -EAGAIN;
|
||||||
|
ch &= UART_RXFIFO_DATA;
|
||||||
|
|
||||||
|
return (!ch) ? -EAGAIN : ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sifive_serial_setbrg(struct udevice *dev, int baudrate)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct clk clk;
|
||||||
|
struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
err = clk_get_by_index(dev, 0, &clk);
|
||||||
|
if (!err) {
|
||||||
|
err = clk_get_rate(&clk);
|
||||||
|
if (!IS_ERR_VALUE(err))
|
||||||
|
platdata->clock = err;
|
||||||
|
} else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
|
||||||
|
debug("SiFive UART failed to get clock\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!platdata->clock)
|
||||||
|
platdata->clock = dev_read_u32_default(dev, "clock-frequency", 0);
|
||||||
|
if (!platdata->clock) {
|
||||||
|
debug("SiFive UART clock not defined\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sifive_serial_setbrg(platdata->regs, platdata->clock, baudrate);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sifive_serial_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
/* No need to reinitialize the UART after relocation */
|
||||||
|
if (gd->flags & GD_FLG_RELOC)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
platdata->saved_input_char = 0;
|
||||||
|
_sifive_serial_init(platdata->regs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sifive_serial_getc(struct udevice *dev)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
|
||||||
|
struct uart_sifive *regs = platdata->regs;
|
||||||
|
|
||||||
|
if (platdata->saved_input_char > 0) {
|
||||||
|
c = platdata->saved_input_char;
|
||||||
|
platdata->saved_input_char = 0;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((c = _sifive_serial_getc(regs)) == -EAGAIN) ;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sifive_serial_putc(struct udevice *dev, const char ch)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
while ((rc = _sifive_serial_putc(platdata->regs, ch)) == -EAGAIN) ;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sifive_serial_pending(struct udevice *dev, bool input)
|
||||||
|
{
|
||||||
|
struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
|
||||||
|
struct uart_sifive *regs = platdata->regs;
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
if (platdata->saved_input_char > 0)
|
||||||
|
return 1;
|
||||||
|
platdata->saved_input_char = _sifive_serial_getc(regs);
|
||||||
|
return (platdata->saved_input_char > 0) ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
return !!(readl(®s->txfifo) & UART_TXFIFO_FULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sifive_serial_ofdata_to_platdata(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
platdata->regs = (struct uart_sifive *)dev_read_addr(dev);
|
||||||
|
if (IS_ERR(platdata->regs))
|
||||||
|
return PTR_ERR(platdata->regs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dm_serial_ops sifive_serial_ops = {
|
||||||
|
.putc = sifive_serial_putc,
|
||||||
|
.getc = sifive_serial_getc,
|
||||||
|
.pending = sifive_serial_pending,
|
||||||
|
.setbrg = sifive_serial_setbrg,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id sifive_serial_ids[] = {
|
||||||
|
{ .compatible = "sifive,uart0" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(serial_sifive) = {
|
||||||
|
.name = "serial_sifive",
|
||||||
|
.id = UCLASS_SERIAL,
|
||||||
|
.of_match = sifive_serial_ids,
|
||||||
|
.ofdata_to_platdata = sifive_serial_ofdata_to_platdata,
|
||||||
|
.platdata_auto_alloc_size = sizeof(struct sifive_uart_platdata),
|
||||||
|
.probe = sifive_serial_probe,
|
||||||
|
.ops = &sifive_serial_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_UART_SIFIVE
|
||||||
|
static inline void _debug_uart_init(void)
|
||||||
|
{
|
||||||
|
struct uart_sifive *regs =
|
||||||
|
(struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
|
||||||
|
|
||||||
|
_sifive_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK,
|
||||||
|
CONFIG_BAUDRATE);
|
||||||
|
_sifive_serial_init(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _debug_uart_putc(int ch)
|
||||||
|
{
|
||||||
|
struct uart_sifive *regs =
|
||||||
|
(struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
|
||||||
|
|
||||||
|
while (_sifive_serial_putc(regs, ch) == -EAGAIN)
|
||||||
|
WATCHDOG_RESET();
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_UART_FUNCS
|
||||||
|
|
||||||
|
#endif
|
|
@ -126,6 +126,13 @@ config OMAP_TIMER
|
||||||
help
|
help
|
||||||
Select this to enable an timer for Omap devices.
|
Select this to enable an timer for Omap devices.
|
||||||
|
|
||||||
|
config RISCV_TIMER
|
||||||
|
bool "RISC-V timer support"
|
||||||
|
depends on TIMER && RISCV
|
||||||
|
help
|
||||||
|
Select this to enable support for the timer as defined
|
||||||
|
by the RISC-V privileged architecture spec.
|
||||||
|
|
||||||
config ROCKCHIP_TIMER
|
config ROCKCHIP_TIMER
|
||||||
bool "Rockchip timer support"
|
bool "Rockchip timer support"
|
||||||
depends on TIMER
|
depends on TIMER
|
||||||
|
|
|
@ -13,6 +13,7 @@ obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence-ttc.o
|
||||||
obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o
|
obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o
|
||||||
obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
|
obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
|
||||||
obj-$(CONFIG_OMAP_TIMER) += omap-timer.o
|
obj-$(CONFIG_OMAP_TIMER) += omap-timer.o
|
||||||
|
obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o
|
||||||
obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
|
obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
|
||||||
obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o
|
obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o
|
||||||
obj-$(CONFIG_STI_TIMER) += sti-timer.o
|
obj-$(CONFIG_STI_TIMER) += sti-timer.o
|
||||||
|
|
56
drivers/timer/riscv_timer.c
Normal file
56
drivers/timer/riscv_timer.c
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*
|
||||||
|
* RISC-V privileged architecture defined generic timer driver
|
||||||
|
*
|
||||||
|
* This driver relies on RISC-V platform codes to provide the essential API
|
||||||
|
* riscv_get_time() which is supposed to return the timer counter as defined
|
||||||
|
* by the RISC-V privileged architecture spec.
|
||||||
|
*
|
||||||
|
* This driver can be used in both M-mode and S-mode U-Boot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <timer.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* riscv_get_time() - get the timer counter
|
||||||
|
*
|
||||||
|
* Platform codes should provide this API in order to make this driver function.
|
||||||
|
*
|
||||||
|
* @time: the 64-bit timer count as defined by the RISC-V privileged
|
||||||
|
* architecture spec.
|
||||||
|
* @return: 0 on success, -ve on error.
|
||||||
|
*/
|
||||||
|
extern int riscv_get_time(u64 *time);
|
||||||
|
|
||||||
|
static int riscv_timer_get_count(struct udevice *dev, u64 *count)
|
||||||
|
{
|
||||||
|
return riscv_get_time(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv_timer_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||||
|
|
||||||
|
/* clock frequency was passed from the cpu driver as driver data */
|
||||||
|
uc_priv->clock_rate = dev->driver_data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct timer_ops riscv_timer_ops = {
|
||||||
|
.get_count = riscv_timer_get_count,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(riscv_timer) = {
|
||||||
|
.name = "riscv_timer",
|
||||||
|
.id = UCLASS_TIMER,
|
||||||
|
.probe = riscv_timer_probe,
|
||||||
|
.ops = &riscv_timer_ops,
|
||||||
|
.flags = DM_FLAG_PRE_RELOC,
|
||||||
|
};
|
|
@ -14,6 +14,8 @@
|
||||||
* @device_id: Driver-defined device identifier
|
* @device_id: Driver-defined device identifier
|
||||||
* @family: DMTF CPU Family identifier
|
* @family: DMTF CPU Family identifier
|
||||||
* @id: DMTF CPU Processor identifier
|
* @id: DMTF CPU Processor identifier
|
||||||
|
* @timebase_freq: the current frequency at which the cpu timer timebase
|
||||||
|
* registers are updated (in Hz)
|
||||||
*
|
*
|
||||||
* This can be accessed with dev_get_parent_platdata() for any UCLASS_CPU
|
* This can be accessed with dev_get_parent_platdata() for any UCLASS_CPU
|
||||||
* device.
|
* device.
|
||||||
|
@ -24,6 +26,7 @@ struct cpu_platdata {
|
||||||
ulong device_id;
|
ulong device_id;
|
||||||
u16 family;
|
u16 family;
|
||||||
u32 id[2];
|
u32 id[2];
|
||||||
|
u32 timebase_freq;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* CPU features - mostly just a placeholder for now */
|
/* CPU features - mostly just a placeholder for now */
|
||||||
|
|
Loading…
Add table
Reference in a new issue