lib: utils: reset: Add T-HEAD sample platform reset driver

This driver is for T-HEAD test chip, fpga. It could work with
all T-HEAD riscv processors: C9xx series.

example1: (Using io-regs for reset)
reset: reset-sample {
	compatible = "thead,reset-sample";
	plic-delegate = <0xff 0xd81ffffc>;
	entry-reg = <0xff 0xff019050>;
	entry-cnt = <4>;
	control-reg = <0xff 0xff015004>;
	control-val = <0x1c>;
	csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>;
};

example2: (Using csr-regs for reset)
reset: reset-sample {
	compatible = "thead,reset-sample";
	plic-delegate = <0xff 0xd81ffffc>;
	using-csr-reset;
	csr-copy = <0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc
		    0x3b0 0x3b1 0x3b2 0x3b3
		    0x3b4 0x3b5 0x3b6 0x3b7
		    0x3a0>;
};

example3: (Only delegate plic enable to S-mode)
reset: reset-sample {
	compatible = "thead,reset-sample";
	plic-delegate = <0xff 0xd81ffffc>;
};

After this patch, all T-HEAD c9xx would use platform/generic with fw_dynamic
as default:

CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=generic FW_PIC=y /usr/bin/make

The platform/thead will be deprecated.

Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
This commit is contained in:
Guo Ren 2021-04-17 16:26:17 +00:00 committed by Anup Patel
parent c5d0645052
commit 49e422c5ad
7 changed files with 214 additions and 0 deletions

View file

@ -157,6 +157,11 @@ void csr_write_num(int csr_num, unsigned long val);
__asm__ __volatile__("wfi" ::: "memory"); \
} while (0)
#define ebreak() \
do { \
__asm__ __volatile__("ebreak" ::: "memory"); \
} while (0)
/* Get current HART id */
#define current_hartid() ((unsigned int)csr_read(CSR_MHARTID))

View file

@ -18,6 +18,9 @@
#define RISCV_FENCE(p, s) \
__asm__ __volatile__ ("fence " #p "," #s : : : "memory")
#define RISCV_FENCE_I \
__asm__ __volatile__ ("fence.i" : : : "memory")
/* Read & Write Memory barrier */
#define mb() RISCV_FENCE(iorw,iorw)

View file

@ -13,10 +13,12 @@
extern struct fdt_reset fdt_reset_sifive;
extern struct fdt_reset fdt_reset_htif;
extern struct fdt_reset fdt_reset_thead;
static struct fdt_reset *reset_drivers[] = {
&fdt_reset_sifive,
&fdt_reset_htif,
&fdt_reset_thead,
};
static struct fdt_reset *current_driver = NULL;

View file

@ -0,0 +1,132 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <libfdt.h>
#include <sbi/riscv_io.h>
#include <sbi/sbi_bitops.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_scratch.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/reset/fdt_reset.h>
#include "fdt_reset_thead.h"
struct custom_csr custom_csr[MAX_CUSTOM_CSR];
#define CSR_OPCODE 0x39073
static void clone_csrs(int cnt)
{
unsigned long i;
for (i = 0; i < cnt; i++) {
/* Write csr BIT[31 - 20] to stub */
__reset_thead_csr_stub[3*i + 1] =
CSR_OPCODE | (custom_csr[i].index << 20);
/* Mask csr BIT[31 - 20] */
*(u32 *)&__fdt_reset_thead_csrr &= BIT(20) - 1;
smp_mb();
/* Write csr BIT[31 - 20] to __fdt_reset_thead_csrr */
*(u32 *)&__fdt_reset_thead_csrr |= custom_csr[i].index << 20;
smp_mb();
RISCV_FENCE_I;
custom_csr[i].value = __fdt_reset_thead_csrr();
}
}
extern void __thead_pre_start_warm(void);
static int thead_reset_init(void *fdt, int nodeoff,
const struct fdt_match *match)
{
void *p;
const fdt64_t *val;
const fdt32_t *val_w;
int len, i, cnt;
u32 t, tmp = 0;
/* Prepare clone csrs */
val_w = fdt_getprop(fdt, nodeoff, "csr-copy", &len);
if (len > 0 && val_w) {
cnt = len / sizeof(fdt32_t);
if (cnt > MAX_CUSTOM_CSR)
sbi_hart_hang();
for (i = 0; i < cnt; i++) {
custom_csr[i].index = fdt32_to_cpu(val_w[i]);
}
}
if (cnt)
clone_csrs(cnt);
/* Delegate plic enable regs for S-mode */
val = fdt_getprop(fdt, nodeoff, "plic-delegate", &len);
if (len > 0 && val) {
p = (void *)(ulong)fdt64_to_cpu(*val);
writel(BIT(0), p);
}
/* Old reset method for secondary harts */
if (fdt_getprop(fdt, nodeoff, "using-csr-reset", &len)) {
csr_write(0x7c7, (ulong)&__thead_pre_start_warm);
csr_write(0x7c6, -1);
}
/* Custom reset method for secondary harts */
val = fdt_getprop(fdt, nodeoff, "entry-reg", &len);
if (len > 0 && val) {
p = (void *)(ulong)fdt64_to_cpu(*val);
val_w = fdt_getprop(fdt, nodeoff, "entry-cnt", &len);
if (len > 0 && val_w) {
tmp = fdt32_to_cpu(*val_w);
for (i = 0; i < tmp; i++) {
t = (ulong)&__thead_pre_start_warm;
writel(t, p + (8 * i));
t = (u64)(ulong)&__thead_pre_start_warm >> 32;
writel(t, p + (8 * i) + 4);
}
}
val = fdt_getprop(fdt, nodeoff, "control-reg", &len);
if (len > 0 && val) {
p = (void *)(ulong)fdt64_to_cpu(*val);
val_w = fdt_getprop(fdt, nodeoff, "control-val", &len);
if (len > 0 && val_w) {
tmp = fdt32_to_cpu(*val_w);
tmp |= readl(p);
writel(tmp, p);
}
}
}
return 0;
}
int thead_system_reset_check(u32 type, u32 reason)
{
return 1;
}
void thead_system_reset(u32 type, u32 reason)
{
ebreak();
}
static const struct fdt_match thead_reset_match[] = {
{ .compatible = "thead,reset-sample" },
{ },
};
struct fdt_reset fdt_reset_thead = {
.match_table = thead_reset_match,
.init = thead_reset_init,
.system_reset_check = thead_system_reset_check,
.system_reset = thead_system_reset
};

View file

@ -0,0 +1,23 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef __FDT_RESET_THEAD_H__
#define __FDT_RESET_THEAD_H__
#define MAX_CUSTOM_CSR 32
#ifndef __ASSEMBLER__
struct custom_csr {
unsigned long index;
unsigned long value;
};
u64 __fdt_reset_thead_csrr(void);
extern struct custom_csr custom_csr[MAX_CUSTOM_CSR];
extern u32 __reset_thead_csr_stub[];
#endif /* __ASSEMBLER__ */
#endif /* __FDT_RESET_THEAD_H__ */

View file

@ -0,0 +1,47 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sbi/riscv_asm.h>
#include "fdt_reset_thead.h"
/*
* csrrs rd, csr, rs1
* |31 20|19 15|14 12|11 7|6 0|
* csr rs1 010 rd 1110011
*/
#define CSR_STUB addi x0, x0, 0
.option norvc
.align 3
.global __fdt_reset_thead_csrr
__fdt_reset_thead_csrr:
csrrs a0, 0, x0
ret
.align 3
.global __thead_pre_start_warm
__thead_pre_start_warm:
/*
* Clear L1 cache & BTB & BHT ...
*/
li t1, 0x70013
csrw 0x7c2, t1
fence rw,rw
lla t1, custom_csr
.global __reset_thead_csr_stub
__reset_thead_csr_stub:
.rept MAX_CUSTOM_CSR
REG_L t2, 8(t1)
CSR_STUB
addi t1, t1, 16
.endr
/*
* Clear L1 cache & BTB & BHT ...
*/
li t1, 0x70013
csrw 0x7c2, t1
fence rw,rw
j _start_warm

View file

@ -10,3 +10,5 @@
libsbiutils-objs-y += reset/fdt_reset.o
libsbiutils-objs-y += reset/fdt_reset_htif.o
libsbiutils-objs-y += reset/fdt_reset_sifive.o
libsbiutils-objs-y += reset/fdt_reset_thead.o
libsbiutils-objs-y += reset/fdt_reset_thead_asm.o