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
@ -22,6 +22,7 @@ source "board/emulation/qemu-riscv/Kconfig"
|
||||
|
||||
# platform-specific options below
|
||||
source "arch/riscv/cpu/ax25/Kconfig"
|
||||
source "arch/riscv/cpu/qemu/Kconfig"
|
||||
|
||||
# architecture-specific options below
|
||||
|
||||
@ -44,6 +45,40 @@ config ARCH_RV64I
|
||||
|
||||
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
|
||||
bool "Emit compressed instructions"
|
||||
default y
|
||||
@ -55,15 +90,30 @@ config RISCV_ISA_C
|
||||
config RISCV_ISA_A
|
||||
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
|
||||
bool
|
||||
|
||||
config 64BIT
|
||||
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
|
||||
|
@ -17,8 +17,15 @@ endif
|
||||
ifeq ($(CONFIG_RISCV_ISA_C),y)
|
||||
ARCH_C = c
|
||||
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)
|
||||
CFLAGS_EFI += $(ARCH_FLAGS)
|
||||
|
@ -4,4 +4,4 @@
|
||||
|
||||
extra-y = start.o
|
||||
|
||||
obj-y += cpu.o
|
||||
obj-y += cpu.o mtrap.o
|
||||
|
@ -1,7 +1,14 @@
|
||||
config RISCV_NDS
|
||||
bool "AndeStar V5 ISA support"
|
||||
default n
|
||||
bool
|
||||
help
|
||||
Say Y here if you plan to run U-Boot on AndeStar v5
|
||||
platforms and use some specific features which are
|
||||
provided by Andes Technology AndeStar V5 Families.
|
||||
Run U-Boot on AndeStar V5 platforms and use some specific features
|
||||
which are 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)
|
||||
{
|
||||
#ifndef CONFIG_SYS_ICACHE_OFF
|
||||
#ifdef CONFIG_RISCV_NDS
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"ori t0, t1, 0x1\n\t"
|
||||
@ -22,7 +22,7 @@ void icache_enable(void)
|
||||
void icache_disable(void)
|
||||
{
|
||||
#ifndef CONFIG_SYS_ICACHE_OFF
|
||||
#ifdef CONFIG_RISCV_NDS
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
asm volatile (
|
||||
"fence.i\n\t"
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
@ -36,7 +36,7 @@ void icache_disable(void)
|
||||
void dcache_enable(void)
|
||||
{
|
||||
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||
#ifdef CONFIG_RISCV_NDS
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"ori t0, t1, 0x2\n\t"
|
||||
@ -49,7 +49,7 @@ void dcache_enable(void)
|
||||
void dcache_disable(void)
|
||||
{
|
||||
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||
#ifdef CONFIG_RISCV_NDS
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
asm volatile (
|
||||
"fence\n\t"
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
@ -64,7 +64,7 @@ int icache_status(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_RISCV_NDS
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"andi %0, t1, 0x01\n\t"
|
||||
@ -81,7 +81,7 @@ int dcache_status(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_RISCV_NDS
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"andi %0, t1, 0x02\n\t"
|
||||
|
@ -4,7 +4,12 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <log.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
|
||||
@ -12,44 +17,79 @@
|
||||
*/
|
||||
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)
|
||||
{
|
||||
#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'));
|
||||
#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];
|
||||
char *s = name;
|
||||
int bit;
|
||||
#ifdef CONFIG_CPU
|
||||
int ret;
|
||||
|
||||
s += sprintf(name, "rv");
|
||||
bit = csr_read(misa) >> (sizeof(long) * 8 - 2);
|
||||
s += sprintf(s, isa_bits[bit]);
|
||||
|
||||
supports_extension('i') ? *s++ = 'i' : 'r';
|
||||
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);
|
||||
/* probe cpus so that RISC-V timer can be bound */
|
||||
ret = cpu_probe_all();
|
||||
if (ret)
|
||||
return log_msg_ret("RISC-V cpus probe failed\n", ret);
|
||||
#endif
|
||||
|
||||
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 <dm.h>
|
||||
|
||||
/*
|
||||
* cleanup_before_linux() is called just before we call linux
|
||||
@ -19,3 +20,16 @@ int cleanup_before_linux(void)
|
||||
|
||||
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 <elf.h>
|
||||
#include <asm/encoding.h>
|
||||
#include <generated/asm-offsets.h>
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
#define LREG lw
|
||||
@ -70,6 +71,9 @@ call_board_init_f_0:
|
||||
|
||||
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 */
|
||||
la t5, board_init_f
|
||||
jr t5 /* jump to board_init_f() */
|
||||
@ -198,92 +202,3 @@ call_board_init_r:
|
||||
* jump to it ...
|
||||
*/
|
||||
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__
|
||||
|
||||
#define xcsr(csr) #csr
|
||||
|
||||
#define csr_swap(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrw %0, " #csr ", %1" \
|
||||
__asm__ __volatile__ ("csrrw %0, " xcsr(csr) ", %1" \
|
||||
: "=r" (__v) : "rK" (__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
@ -73,7 +75,7 @@
|
||||
#define csr_read(csr) \
|
||||
({ \
|
||||
register unsigned long __v; \
|
||||
__asm__ __volatile__ ("csrr %0, " #csr \
|
||||
__asm__ __volatile__ ("csrr %0, " xcsr(csr) \
|
||||
: "=r" (__v) : \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
@ -82,7 +84,7 @@
|
||||
#define csr_write(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrw " #csr ", %0" \
|
||||
__asm__ __volatile__ ("csrw " xcsr(csr) ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
@ -90,7 +92,7 @@
|
||||
#define csr_read_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrs %0, " #csr ", %1" \
|
||||
__asm__ __volatile__ ("csrrs %0, " xcsr(csr) ", %1" \
|
||||
: "=r" (__v) : "rK" (__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
@ -99,7 +101,7 @@
|
||||
#define csr_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrs " #csr ", %0" \
|
||||
__asm__ __volatile__ ("csrs " xcsr(csr) ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
@ -107,7 +109,7 @@
|
||||
#define csr_read_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrc %0, " #csr ", %1" \
|
||||
__asm__ __volatile__ ("csrrc %0, " xcsr(csr) ", %1" \
|
||||
: "=r" (__v) : "rK" (__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
@ -116,7 +118,7 @@
|
||||
#define csr_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrc " #csr ", %0" \
|
||||
__asm__ __volatile__ ("csrc " xcsr(csr) ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
@ -85,6 +85,21 @@
|
||||
#define IRQ_COP 12
|
||||
#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_NMIVEC 0x00001004
|
||||
#define DEFAULT_MTVEC 0x00001010
|
||||
@ -152,6 +167,227 @@
|
||||
#define RISCV_PGSHIFT 12
|
||||
#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_CSR_ENCODING_H */
|
||||
|
@ -12,6 +12,10 @@
|
||||
|
||||
/* Architecture-specific 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>
|
||||
|
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_GO) += boot.o
|
||||
obj-y += cache.o
|
||||
obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
|
||||
obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
|
||||
obj-y += interrupts.o
|
||||
obj-y += reset.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 (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/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)
|
||||
{
|
||||
@ -72,34 +101,3 @@ __attribute__((weak)) void external_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
|
||||
default 0x140000 if ENV_IS_IN_SPI_FLASH
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
select RISCV_NDS
|
||||
|
||||
endif
|
||||
|
@ -3,6 +3,5 @@ M: Rick Chen <rick@andestech.com>
|
||||
S: Maintained
|
||||
F: board/AndesTech/ax25-ae350/
|
||||
F: include/configs/ax25-ae350.h
|
||||
F: configs/a25-ae350_32_defconfig
|
||||
F: configs/ax25-ae350_64_defconfig
|
||||
F: configs/ax25-ae350_defconfig
|
||||
F: configs/ae350_rv32_defconfig
|
||||
F: configs/ae350_rv64_defconfig
|
||||
|
@ -18,6 +18,7 @@ config SYS_TEXT_BASE
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
select QEMU_RISCV
|
||||
imply SYS_NS16550
|
||||
imply VIRTIO_MMIO
|
||||
imply VIRTIO_NET
|
||||
@ -32,5 +33,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
imply CMD_FAT
|
||||
imply BOARD_LATE_INIT
|
||||
imply OF_BOARD_SETUP
|
||||
imply SIFIVE_SERIAL
|
||||
|
||||
endif
|
||||
|
@ -25,7 +25,7 @@ Build and boot steps
|
||||
|
||||
build:
|
||||
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
|
||||
====================
|
||||
|
@ -13,3 +13,9 @@ config CPU_MPC83XX
|
||||
select CLK_MPC83XX
|
||||
help
|
||||
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_CPU_MPC83XX) += mpc83xx_cpu.o
|
||||
obj-$(CONFIG_CPU_RISCV) += riscv_cpu.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
|
||||
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
|
||||
bool "STMicroelectronics STM32"
|
||||
depends on STM32_SERIAL
|
||||
@ -679,6 +686,12 @@ 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 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
|
||||
bool "STMicroelectronics on-chip UART"
|
||||
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_OMAP_SERIAL) += serial_omap.o
|
||||
obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
|
||||
obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
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
|
||||
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
|
||||
bool "Rockchip timer support"
|
||||
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_MPC83XX_TIMER) += mpc83xx_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_SANDBOX_TIMER) += sandbox_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
|
||||
* @family: DMTF CPU Family 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
|
||||
* device.
|
||||
@ -24,6 +26,7 @@ struct cpu_platdata {
|
||||
ulong device_id;
|
||||
u16 family;
|
||||
u32 id[2];
|
||||
u32 timebase_freq;
|
||||
};
|
||||
|
||||
/* CPU features - mostly just a placeholder for now */
|
||||
|
Loading…
Reference in New Issue
Block a user