GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
|
||||
extra-y = start.o
|
||||
|
||||
obj-y += cpu.o mtrap.o
|
||||
@@ -0,0 +1,24 @@
|
||||
config RISCV_NDS
|
||||
bool
|
||||
select ARCH_EARLY_INIT_R
|
||||
imply CPU
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER
|
||||
imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE)
|
||||
imply ANDES_PLMT if (RISCV_MMODE || SPL_RISCV_MMODE)
|
||||
imply SPL_CPU_SUPPORT
|
||||
imply SPL_OPENSBI
|
||||
imply SPL_LOAD_FIT
|
||||
help
|
||||
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"
|
||||
depends on RISCV_MMODE || SPL_RISCV_MMODE
|
||||
help
|
||||
Provide Andes Technology AndeStar V5 families specific cache support.
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2017 Andes Technology Corporation
|
||||
# Rick Chen, Andes Technology Corporation <rick@andestech.com>
|
||||
|
||||
obj-y := cpu.o
|
||||
obj-y += cache.o
|
||||
@@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2017 Andes Technology Corporation
|
||||
* Rick Chen, Andes Technology Corporation <rick@andestech.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <cpu_func.h>
|
||||
#include <dm.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <cache.h>
|
||||
#include <asm/csr.h>
|
||||
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
|
||||
/* mcctlcommand */
|
||||
#define CCTL_REG_MCCTLCOMMAND_NUM 0x7cc
|
||||
|
||||
/* D-cache operation */
|
||||
#define CCTL_L1D_WBINVAL_ALL 6
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_V5L2_CACHE
|
||||
static void _cache_enable(void)
|
||||
{
|
||||
struct udevice *dev = NULL;
|
||||
|
||||
uclass_find_first_device(UCLASS_CACHE, &dev);
|
||||
|
||||
if (dev)
|
||||
cache_enable(dev);
|
||||
}
|
||||
|
||||
static void _cache_disable(void)
|
||||
{
|
||||
struct udevice *dev = NULL;
|
||||
|
||||
uclass_find_first_device(UCLASS_CACHE, &dev);
|
||||
|
||||
if (dev)
|
||||
cache_disable(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
void flush_dcache_all(void)
|
||||
{
|
||||
#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
|
||||
csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void flush_dcache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
flush_dcache_all();
|
||||
}
|
||||
|
||||
void invalidate_dcache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
flush_dcache_all();
|
||||
}
|
||||
|
||||
void icache_enable(void)
|
||||
{
|
||||
#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"ori t0, t1, 0x1\n\t"
|
||||
"csrw mcache_ctl, t0\n\t"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void icache_disable(void)
|
||||
{
|
||||
#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
|
||||
asm volatile (
|
||||
"fence.i\n\t"
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"andi t0, t1, ~0x1\n\t"
|
||||
"csrw mcache_ctl, t0\n\t"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void dcache_enable(void)
|
||||
{
|
||||
#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"ori t0, t1, 0x2\n\t"
|
||||
"csrw mcache_ctl, t0\n\t"
|
||||
);
|
||||
#endif
|
||||
#ifdef CONFIG_V5L2_CACHE
|
||||
_cache_enable();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void dcache_disable(void)
|
||||
{
|
||||
#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
|
||||
csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL);
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"andi t0, t1, ~0x2\n\t"
|
||||
"csrw mcache_ctl, t0\n\t"
|
||||
);
|
||||
#endif
|
||||
#ifdef CONFIG_V5L2_CACHE
|
||||
_cache_disable();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
int icache_status(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"andi %0, t1, 0x01\n\t"
|
||||
: "=r" (ret)
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dcache_status(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_RISCV_NDS_CACHE
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) || CONFIG_IS_ENABLED(SPL_RISCV_MMODE)
|
||||
asm volatile (
|
||||
"csrr t1, mcache_ctl\n\t"
|
||||
"andi %0, t1, 0x02\n\t"
|
||||
: "=r" (ret)
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2017 Andes Technology Corporation
|
||||
* Rick Chen, Andes Technology Corporation <rick@andestech.com>
|
||||
*/
|
||||
|
||||
/* CPU specific code */
|
||||
#include <common.h>
|
||||
#include <cpu_func.h>
|
||||
#include <irq_func.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
/*
|
||||
* cleanup_before_linux() is called just before we call linux
|
||||
* it prepares the processor for linux
|
||||
*
|
||||
* we disable interrupt and caches.
|
||||
*/
|
||||
int cleanup_before_linux(void)
|
||||
{
|
||||
disable_interrupts();
|
||||
|
||||
/* turn off I/D-cache */
|
||||
cache_flush();
|
||||
icache_disable();
|
||||
dcache_disable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// 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 <log.h>
|
||||
#include <asm/encoding.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
|
||||
/*
|
||||
* The variables here must be stored in the data section since they are used
|
||||
* before the bss section is available.
|
||||
*/
|
||||
#ifdef CONFIG_OF_PRIOR_STAGE
|
||||
phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
|
||||
#endif
|
||||
#ifndef CONFIG_XIP
|
||||
u32 hart_lottery __attribute__((section(".data"))) = 0;
|
||||
|
||||
/*
|
||||
* The main hart running U-Boot has acquired available_harts_lock until it has
|
||||
* finished initialization of global data.
|
||||
*/
|
||||
u32 available_harts_lock = 1;
|
||||
#endif
|
||||
|
||||
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 */
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE)
|
||||
return csr_read(CSR_MISA) & (1 << (ext - 'a'));
|
||||
#else /* !CONFIG_IS_ENABLED(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_IS_ENABLED(RISCV_MMODE) */
|
||||
#endif /* CONFIG_CPU */
|
||||
}
|
||||
|
||||
static int riscv_cpu_probe(void)
|
||||
{
|
||||
#ifdef CONFIG_CPU
|
||||
int ret;
|
||||
|
||||
/* 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(CSR_FCSR, 0);
|
||||
}
|
||||
|
||||
if (CONFIG_IS_ENABLED(RISCV_MMODE)) {
|
||||
/*
|
||||
* Enable perf counters for cycle, time,
|
||||
* and instret counters only
|
||||
*/
|
||||
csr_write(CSR_MCOUNTEREN, GENMASK(2, 0));
|
||||
|
||||
/* Disable paging */
|
||||
if (supports_extension('s'))
|
||||
csr_write(CSR_SATP, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_early_init_r(void)
|
||||
{
|
||||
return riscv_cpu_probe();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
|
||||
config GENERIC_RISCV
|
||||
bool
|
||||
select ARCH_EARLY_INIT_R
|
||||
imply CPU
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER
|
||||
imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
|
||||
imply CMD_CPU
|
||||
imply SPL_CPU_SUPPORT
|
||||
imply SPL_OPENSBI
|
||||
imply SPL_LOAD_FIT
|
||||
@@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
|
||||
obj-y += dram.o
|
||||
obj-y += cpu.o
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <irq_func.h>
|
||||
|
||||
/*
|
||||
* cleanup_before_linux() is called just before we call linux
|
||||
* it prepares the processor for linux
|
||||
*
|
||||
* we disable interrupt and caches.
|
||||
*/
|
||||
int cleanup_before_linux(void)
|
||||
{
|
||||
disable_interrupts();
|
||||
|
||||
cache_flush();
|
||||
|
||||
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,
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <init.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
return fdtdec_setup_mem_size_base();
|
||||
}
|
||||
|
||||
int dram_init_banksize(void)
|
||||
{
|
||||
return fdtdec_setup_memory_banksize();
|
||||
}
|
||||
|
||||
ulong board_get_usable_ram_top(ulong total_size)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
/*
|
||||
* Ensure that we run from first 4GB so that all
|
||||
* addresses used by U-Boot are 32bit addresses.
|
||||
*
|
||||
* This in-turn ensures that 32bit DMA capable
|
||||
* devices work fine because DMA mapping APIs will
|
||||
* provide 32bit DMA addresses only.
|
||||
*/
|
||||
if (gd->ram_top > SZ_4G)
|
||||
return SZ_4G;
|
||||
#endif
|
||||
return gd->ram_top;
|
||||
}
|
||||
@@ -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)
|
||||
@@ -0,0 +1,414 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Startup 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>
|
||||
*/
|
||||
|
||||
#include <asm-offsets.h>
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <elf.h>
|
||||
#include <asm/encoding.h>
|
||||
#include <generated/asm-offsets.h>
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
#define LREG lw
|
||||
#define SREG sw
|
||||
#define REGBYTES 4
|
||||
#define RELOC_TYPE R_RISCV_32
|
||||
#define SYM_INDEX 0x8
|
||||
#define SYM_SIZE 0x10
|
||||
#else
|
||||
#define LREG ld
|
||||
#define SREG sd
|
||||
#define REGBYTES 8
|
||||
#define RELOC_TYPE R_RISCV_64
|
||||
#define SYM_INDEX 0x20
|
||||
#define SYM_SIZE 0x18
|
||||
#endif
|
||||
|
||||
.section .data
|
||||
secondary_harts_relocation_error:
|
||||
.ascii "Relocation of secondary harts has failed, error %d\n"
|
||||
|
||||
.section .text
|
||||
.globl _start
|
||||
_start:
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE)
|
||||
csrr a0, CSR_MHARTID
|
||||
#endif
|
||||
|
||||
/* save hart id and dtb pointer */
|
||||
mv tp, a0
|
||||
mv s1, a1
|
||||
|
||||
la t0, trap_entry
|
||||
csrw MODE_PREFIX(tvec), t0
|
||||
|
||||
/* mask all interrupts */
|
||||
csrw MODE_PREFIX(ie), zero
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* check if hart is within range */
|
||||
/* tp: hart id */
|
||||
li t0, CONFIG_NR_CPUS
|
||||
bge tp, t0, hart_out_of_bounds_loop
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* set xSIE bit to receive IPIs */
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE)
|
||||
li t0, MIE_MSIE
|
||||
#else
|
||||
li t0, SIE_SSIE
|
||||
#endif
|
||||
csrs MODE_PREFIX(ie), t0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set stackpointer in internal/ex RAM to call board_init_f
|
||||
*/
|
||||
call_board_init_f:
|
||||
li t0, -16
|
||||
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
|
||||
li t1, CONFIG_SPL_STACK
|
||||
#else
|
||||
li t1, CONFIG_SYS_INIT_SP_ADDR
|
||||
#endif
|
||||
and sp, t1, t0 /* force 16 byte alignment */
|
||||
|
||||
call_board_init_f_0:
|
||||
mv a0, sp
|
||||
jal board_init_f_alloc_reserve
|
||||
|
||||
/*
|
||||
* Set global data pointer here for all harts, uninitialized at this
|
||||
* point.
|
||||
*/
|
||||
mv gp, a0
|
||||
|
||||
/* setup stack */
|
||||
#ifdef CONFIG_SMP
|
||||
/* tp: hart id */
|
||||
slli t0, tp, CONFIG_STACK_SIZE_SHIFT
|
||||
sub sp, a0, t0
|
||||
#else
|
||||
mv sp, a0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_XIP
|
||||
/*
|
||||
* Pick hart to initialize global data and run U-Boot. The other harts
|
||||
* wait for initialization to complete.
|
||||
*/
|
||||
la t0, hart_lottery
|
||||
li s2, 1
|
||||
amoswap.w s2, t1, 0(t0)
|
||||
bnez s2, wait_for_gd_init
|
||||
#else
|
||||
bnez tp, secondary_hart_loop
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF_PRIOR_STAGE
|
||||
la t0, prior_stage_fdt_address
|
||||
SREG s1, 0(t0)
|
||||
#endif
|
||||
|
||||
jal board_init_f_init_reserve
|
||||
|
||||
/* save the boot hart id to global_data */
|
||||
SREG tp, GD_BOOT_HART(gp)
|
||||
|
||||
#ifndef CONFIG_XIP
|
||||
la t0, available_harts_lock
|
||||
fence rw, w
|
||||
amoswap.w zero, zero, 0(t0)
|
||||
|
||||
wait_for_gd_init:
|
||||
la t0, available_harts_lock
|
||||
li t1, 1
|
||||
1: amoswap.w t1, t1, 0(t0)
|
||||
fence r, rw
|
||||
bnez t1, 1b
|
||||
|
||||
/* register available harts in the available_harts mask */
|
||||
li t1, 1
|
||||
sll t1, t1, tp
|
||||
LREG t2, GD_AVAILABLE_HARTS(gp)
|
||||
or t2, t2, t1
|
||||
SREG t2, GD_AVAILABLE_HARTS(gp)
|
||||
|
||||
fence rw, w
|
||||
amoswap.w zero, zero, 0(t0)
|
||||
|
||||
/*
|
||||
* Continue on hart lottery winner, others branch to
|
||||
* secondary_hart_loop.
|
||||
*/
|
||||
bnez s2, secondary_hart_loop
|
||||
#endif
|
||||
|
||||
/* Enable cache */
|
||||
jal icache_enable
|
||||
jal dcache_enable
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART
|
||||
jal debug_uart_init
|
||||
#endif
|
||||
|
||||
mv a0, zero /* a0 <-- boot_flags = 0 */
|
||||
la t5, board_init_f
|
||||
jalr t5 /* jump to board_init_f() */
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
spl_clear_bss:
|
||||
la t0, __bss_start
|
||||
la t1, __bss_end
|
||||
beq t0, t1, spl_stack_gd_setup
|
||||
|
||||
spl_clear_bss_loop:
|
||||
SREG zero, 0(t0)
|
||||
addi t0, t0, REGBYTES
|
||||
blt t0, t1, spl_clear_bss_loop
|
||||
|
||||
spl_stack_gd_setup:
|
||||
jal spl_relocate_stack_gd
|
||||
|
||||
/* skip setup if we did not relocate */
|
||||
beqz a0, spl_call_board_init_r
|
||||
mv s0, a0
|
||||
|
||||
/* setup stack on main hart */
|
||||
#ifdef CONFIG_SMP
|
||||
/* tp: hart id */
|
||||
slli t0, tp, CONFIG_STACK_SIZE_SHIFT
|
||||
sub sp, s0, t0
|
||||
#else
|
||||
mv sp, s0
|
||||
#endif
|
||||
|
||||
/* set new stack and global data pointer on secondary harts */
|
||||
spl_secondary_hart_stack_gd_setup:
|
||||
la a0, secondary_hart_relocate
|
||||
mv a1, s0
|
||||
mv a2, s0
|
||||
mv a3, zero
|
||||
jal smp_call_function
|
||||
|
||||
/* hang if relocation of secondary harts has failed */
|
||||
beqz a0, 1f
|
||||
mv a1, a0
|
||||
la a0, secondary_harts_relocation_error
|
||||
jal printf
|
||||
jal hang
|
||||
|
||||
/* set new global data pointer on main hart */
|
||||
1: mv gp, s0
|
||||
|
||||
spl_call_board_init_r:
|
||||
mv a0, zero
|
||||
mv a1, zero
|
||||
jal board_init_r
|
||||
#endif
|
||||
|
||||
/*
|
||||
* void relocate_code (addr_sp, gd, addr_moni)
|
||||
*
|
||||
* This "function" does not return, instead it continues in RAM
|
||||
* after relocating the monitor code.
|
||||
*
|
||||
*/
|
||||
.globl relocate_code
|
||||
relocate_code:
|
||||
mv s2, a0 /* save addr_sp */
|
||||
mv s3, a1 /* save addr of gd */
|
||||
mv s4, a2 /* save addr of destination */
|
||||
|
||||
/*
|
||||
*Set up the stack
|
||||
*/
|
||||
stack_setup:
|
||||
#ifdef CONFIG_SMP
|
||||
/* tp: hart id */
|
||||
slli t0, tp, CONFIG_STACK_SIZE_SHIFT
|
||||
sub sp, s2, t0
|
||||
#else
|
||||
mv sp, s2
|
||||
#endif
|
||||
|
||||
la t0, _start
|
||||
sub t6, s4, t0 /* t6 <- relocation offset */
|
||||
beq t0, s4, clear_bss /* skip relocation */
|
||||
|
||||
mv t1, s4 /* t1 <- scratch for copy_loop */
|
||||
la t3, __bss_start
|
||||
sub t3, t3, t0 /* t3 <- __bss_start_ofs */
|
||||
add t2, t0, t3 /* t2 <- source end address */
|
||||
|
||||
copy_loop:
|
||||
LREG t5, 0(t0)
|
||||
addi t0, t0, REGBYTES
|
||||
SREG t5, 0(t1)
|
||||
addi t1, t1, REGBYTES
|
||||
blt t0, t2, copy_loop
|
||||
|
||||
/*
|
||||
* Update dynamic relocations after board_init_f
|
||||
*/
|
||||
fix_rela_dyn:
|
||||
la t1, __rel_dyn_start
|
||||
la t2, __rel_dyn_end
|
||||
beq t1, t2, clear_bss
|
||||
add t1, t1, t6 /* t1 <- rela_dyn_start in RAM */
|
||||
add t2, t2, t6 /* t2 <- rela_dyn_end in RAM */
|
||||
|
||||
/*
|
||||
* skip first reserved entry: address, type, addend
|
||||
*/
|
||||
j 10f
|
||||
|
||||
6:
|
||||
LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
|
||||
li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
|
||||
bne t5, t3, 8f /* skip non-RISCV_RELOC entries */
|
||||
LREG t3, -(REGBYTES*3)(t1)
|
||||
LREG t5, -(REGBYTES)(t1) /* t5 <-- addend */
|
||||
add t5, t5, t6 /* t5 <-- location to fix up in RAM */
|
||||
add t3, t3, t6 /* t3 <-- location to fix up in RAM */
|
||||
SREG t5, 0(t3)
|
||||
j 10f
|
||||
|
||||
8:
|
||||
la t4, __dyn_sym_start
|
||||
add t4, t4, t6
|
||||
|
||||
9:
|
||||
LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
|
||||
srli t0, t5, SYM_INDEX /* t0 <--- sym table index */
|
||||
andi t5, t5, 0xFF /* t5 <--- relocation type */
|
||||
li t3, RELOC_TYPE
|
||||
bne t5, t3, 10f /* skip non-addned entries */
|
||||
|
||||
LREG t3, -(REGBYTES*3)(t1)
|
||||
li t5, SYM_SIZE
|
||||
mul t0, t0, t5
|
||||
add s5, t4, t0
|
||||
LREG t0, -(REGBYTES)(t1) /* t0 <-- addend */
|
||||
LREG t5, REGBYTES(s5)
|
||||
add t5, t5, t0
|
||||
add t5, t5, t6 /* t5 <-- location to fix up in RAM */
|
||||
add t3, t3, t6 /* t3 <-- location to fix up in RAM */
|
||||
SREG t5, 0(t3)
|
||||
10:
|
||||
addi t1, t1, (REGBYTES*3)
|
||||
ble t1, t2, 6b
|
||||
|
||||
/*
|
||||
* trap update
|
||||
*/
|
||||
la t0, trap_entry
|
||||
add t0, t0, t6
|
||||
csrw MODE_PREFIX(tvec), t0
|
||||
|
||||
clear_bss:
|
||||
la t0, __bss_start /* t0 <- rel __bss_start in FLASH */
|
||||
add t0, t0, t6 /* t0 <- rel __bss_start in RAM */
|
||||
la t1, __bss_end /* t1 <- rel __bss_end in FLASH */
|
||||
add t1, t1, t6 /* t1 <- rel __bss_end in RAM */
|
||||
beq t0, t1, relocate_secondary_harts
|
||||
|
||||
clbss_l:
|
||||
SREG zero, 0(t0) /* clear loop... */
|
||||
addi t0, t0, REGBYTES
|
||||
blt t0, t1, clbss_l
|
||||
|
||||
relocate_secondary_harts:
|
||||
#ifdef CONFIG_SMP
|
||||
/* send relocation IPI */
|
||||
la t0, secondary_hart_relocate
|
||||
add a0, t0, t6
|
||||
|
||||
/* store relocation offset */
|
||||
mv s5, t6
|
||||
|
||||
mv a1, s2
|
||||
mv a2, s3
|
||||
mv a3, zero
|
||||
jal smp_call_function
|
||||
|
||||
/* hang if relocation of secondary harts has failed */
|
||||
beqz a0, 1f
|
||||
mv a1, a0
|
||||
la a0, secondary_harts_relocation_error
|
||||
jal printf
|
||||
jal hang
|
||||
|
||||
/* restore relocation offset */
|
||||
1: mv t6, s5
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We are done. Do not return, instead branch to second part of board
|
||||
* initialization, now running from RAM.
|
||||
*/
|
||||
call_board_init_r:
|
||||
jal invalidate_icache_all
|
||||
jal flush_dcache_all
|
||||
la t0, board_init_r
|
||||
mv t4, t0 /* offset of board_init_r() */
|
||||
add t4, t4, t6 /* real address of board_init_r() */
|
||||
/*
|
||||
* setup parameters for board_init_r
|
||||
*/
|
||||
mv a0, s3 /* gd_t */
|
||||
mv a1, s4 /* dest_addr */
|
||||
|
||||
/*
|
||||
* jump to it ...
|
||||
*/
|
||||
jr t4 /* jump to board_init_r() */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
hart_out_of_bounds_loop:
|
||||
/* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
|
||||
wfi
|
||||
j hart_out_of_bounds_loop
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* SMP relocation entry */
|
||||
secondary_hart_relocate:
|
||||
/* a1: new sp */
|
||||
/* a2: new gd */
|
||||
/* tp: hart id */
|
||||
|
||||
/* setup stack */
|
||||
slli t0, tp, CONFIG_STACK_SIZE_SHIFT
|
||||
sub sp, a1, t0
|
||||
|
||||
/* update global data pointer */
|
||||
mv gp, a2
|
||||
#endif
|
||||
|
||||
secondary_hart_loop:
|
||||
wfi
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
csrr t0, MODE_PREFIX(ip)
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE)
|
||||
andi t0, t0, MIE_MSIE
|
||||
#else
|
||||
andi t0, t0, SIE_SSIE
|
||||
#endif
|
||||
beqz t0, secondary_hart_loop
|
||||
|
||||
mv a0, tp
|
||||
jal handle_ipi
|
||||
#endif
|
||||
|
||||
j secondary_hart_loop
|
||||
@@ -0,0 +1,82 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Based on arch/riscv/cpu/u-boot.lds, which is
|
||||
* Copyright (C) 2017 Andes Technology Corporation
|
||||
* Rick Chen, Andes Technology Corporation <rick@andestech.com>
|
||||
*
|
||||
* and arch/mips/cpu/u-boot-spl.lds.
|
||||
*/
|
||||
MEMORY { .spl_mem : ORIGIN = IMAGE_TEXT_BASE, LENGTH = IMAGE_MAX_SIZE }
|
||||
MEMORY { .bss_mem : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
|
||||
LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
|
||||
|
||||
OUTPUT_ARCH("riscv")
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.text : {
|
||||
arch/riscv/cpu/start.o (.text)
|
||||
*(.text*)
|
||||
} > .spl_mem
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : {
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
|
||||
} > .spl_mem
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : {
|
||||
*(.data*)
|
||||
} > .spl_mem
|
||||
. = ALIGN(4);
|
||||
|
||||
.got : {
|
||||
__got_start = .;
|
||||
*(.got.plt) *(.got)
|
||||
__got_end = .;
|
||||
} > .spl_mem
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.u_boot_list : {
|
||||
KEEP(*(SORT(.u_boot_list*)));
|
||||
} > .spl_mem
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.binman_sym_table : {
|
||||
__binman_sym_start = .;
|
||||
KEEP(*(SORT(.binman_sym*)));
|
||||
__binman_sym_end = .;
|
||||
} > .spl_mem
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
/DISCARD/ : { *(.rela.plt*) }
|
||||
.rela.dyn : {
|
||||
__rel_dyn_start = .;
|
||||
*(.rela*)
|
||||
__rel_dyn_end = .;
|
||||
} > .spl_mem
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.dynsym : {
|
||||
__dyn_sym_start = .;
|
||||
*(.dynsym)
|
||||
__dyn_sym_end = .;
|
||||
} > .spl_mem
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
_end = .;
|
||||
|
||||
.bss : {
|
||||
__bss_start = .;
|
||||
*(.bss*)
|
||||
. = ALIGN(8);
|
||||
__bss_end = .;
|
||||
} > .bss_mem
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2017 Andes Technology Corporation
|
||||
* Rick Chen, Andes Technology Corporation <rick@andestech.com>
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH("riscv")
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.text : {
|
||||
arch/riscv/cpu/start.o (.text)
|
||||
}
|
||||
|
||||
/* This needs to come before *(.text*) */
|
||||
.efi_runtime : {
|
||||
__efi_runtime_start = .;
|
||||
*(.text.efi_runtime*)
|
||||
*(.rodata.efi_runtime*)
|
||||
*(.data.efi_runtime*)
|
||||
__efi_runtime_stop = .;
|
||||
}
|
||||
|
||||
.text_rest : {
|
||||
*(.text*)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : {
|
||||
__global_pointer$ = . + 0x800;
|
||||
*(.data*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
|
||||
.got : {
|
||||
__got_start = .;
|
||||
*(.got.plt) *(.got)
|
||||
__got_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.u_boot_list : {
|
||||
KEEP(*(SORT(.u_boot_list*)));
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.efi_runtime_rel : {
|
||||
__efi_runtime_rel_start = .;
|
||||
*(.rel*.efi_runtime)
|
||||
*(.rel*.efi_runtime.*)
|
||||
__efi_runtime_rel_stop = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
/DISCARD/ : { *(.rela.plt*) }
|
||||
.rela.dyn : {
|
||||
__rel_dyn_start = .;
|
||||
*(.rela*)
|
||||
__rel_dyn_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.dynsym : {
|
||||
__dyn_sym_start = .;
|
||||
*(.dynsym)
|
||||
__dyn_sym_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
_end = .;
|
||||
|
||||
.bss : {
|
||||
__bss_start = .;
|
||||
*(.bss*)
|
||||
. = ALIGN(8);
|
||||
__bss_end = .;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user