[PATCH v2 2/2] lib: utils: reset: Add T-HEAD sample platform reset driver

Anup Patel Anup.Patel at wdc.com
Wed Apr 21 05:30:29 BST 2021



> -----Original Message-----
> From: guoren at kernel.org <guoren at kernel.org>
> Sent: 17 April 2021 21:56
> To: guoren at kernel.org; Alistair Francis <Alistair.Francis at wdc.com>;
> anup at brainfault.org
> Cc: opensbi at lists.infradead.org; Guo Ren <guoren at linux.alibaba.com>;
> Anup Patel <Anup.Patel at wdc.com>; Atish Patra <Atish.Patra at wdc.com>;
> Xiang W <wxjstz at 126.com>; Bin Meng <bmeng.cn at gmail.com>
> Subject: [PATCH v2 2/2] lib: utils: reset: Add T-HEAD sample platform reset
> driver
> 
> From: Guo Ren <guoren at linux.alibaba.com>
> 
> 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
> 
> dts full example:
> 	cpus {
> 		#address-cells = <1>;
> 		#size-cells = <0>;
> 		timebase-frequency = <0x2dc6c0>;
> 		cpu at 0 {
> 			device_type = "cpu";
> 			reg = <0>;
> 			status = "okay";
> 			compatible = "riscv";
> 			riscv,isa = "rv64imafdcsu";
> 			mmu-type = "riscv,sv39";
> 			cpu0_intc: interrupt-controller {
> 				#interrupt-cells = <1>;
> 				compatible = "riscv,cpu-intc";
> 				interrupt-controller;
> 			};
> 		};
> 		cpu at 1 {
> 			device_type = "cpu";
> 			reg = <1>;
> 			status = "fail";
> 			compatible = "riscv";
> 			riscv,isa = "rv64imafdcsu";
> 			mmu-type = "riscv,sv39";
> 			cpu1_intc: interrupt-controller {
> 				#interrupt-cells = <1>;
> 				compatible = "riscv,cpu-intc";
> 				interrupt-controller;
> 			};
> 		};
> 		cpu at 2 {
> 			device_type = "cpu";
> 			reg = <2>;
> 			status = "fail";
> 			compatible = "riscv";
> 			riscv,isa = "rv64imafdcsu";
> 			mmu-type = "riscv,sv39";
> 			cpu2_intc: interrupt-controller {
> 				#interrupt-cells = <1>;
> 				compatible = "riscv,cpu-intc";
> 				interrupt-controller;
> 			};
> 		};
> 		cpu at 3 {
> 			device_type = "cpu";
> 			reg = <3>;
> 			status = "fail";
> 			compatible = "riscv";
> 			riscv,isa = "rv64imafdcsu";
> 			mmu-type = "riscv,sv39";
> 			cpu3_intc: interrupt-controller {
> 				#interrupt-cells = <1>;
> 				compatible = "riscv,cpu-intc";
> 				interrupt-controller;
> 			};
> 		};
> 	};
> 
> 	soc {
> 		#address-cells = <2>;
> 		#size-cells = <2>;
> 		compatible = "simple-bus";
> 		ranges;
> 
> 		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
> 				>;
> 		};
> 
> 		clint0: clint at ffdc000000 {
> 			compatible = "riscv,clint0";
> 			interrupts-extended = <
> 				&cpu0_intc  3 &cpu0_intc  7
> 				&cpu1_intc  3 &cpu1_intc  7
> 				&cpu2_intc  3 &cpu2_intc  7
> 				&cpu3_intc  3 &cpu3_intc  7
> 				&cpu4_intc  3 &cpu4_intc  7
> 				>;
> 			reg = <0xff 0xdc000000 0x0 0x04000000>;
> 			clint,has-no-64bit-mmio;
> 		};
> 
> 		intc: interrupt-controller at ffd8000000 {
> 			#interrupt-cells = <1>;
> 			compatible = "riscv,plic0";
> 			interrupt-controller;
> 			interrupts-extended = <
> 				&cpu0_intc  0xffffffff &cpu0_intc  9
> 				&cpu1_intc  0xffffffff &cpu1_intc  9
> 				&cpu2_intc  0xffffffff &cpu2_intc  9
> 				&cpu3_intc  0xffffffff &cpu3_intc  9
> 				>;
> 			reg = <0xff 0xd8000000 0x0 0x04000000>;
> 			reg-names = "control";
> 			riscv,max-priority = <7>;
> 			riscv,ndev = <80>;
> 		};
> 	}
> 
> The platform/thead will be deprecated.
> 
> Change in v2 (by Anup):
>  - Clean up includes in fdt_reset_thead.h and keep the minimum.
>  - Add macro of fence.i & ebreak in riscv_asm&barrier.h.
>  - Fixup system_reset_check() for ebreak and test it on hardware.
>  - Add __FDT_RESET_THEAD_H__ in fdt_reset_thead.h.
> 
> Signed-off-by: Guo Ren <guoren at linux.alibaba.com>
> Link: http://lists.infradead.org/pipermail/opensbi/2021-April/000863.html
> Cc: Anup Patel <anup.patel at wdc.com>
> Cc: Atish Patra <atish.patra at wdc.com>
> Cc: Xiang W <wxjstz at 126.com>
> Cc: Bin Meng <bmeng.cn at gmail.com>
> ---

The commit description is quite big. I will trim it at time of merging this patch.

Otherwise, Looks good to me.

Reviewed-by: Anup Patel <anup.patel at wdc.com>

Regards,
Anup

>  include/sbi/riscv_asm.h               |   5 ++
>  include/sbi/riscv_barrier.h           |   3 +
>  lib/utils/reset/fdt_reset.c           |   2 +
>  lib/utils/reset/fdt_reset_thead.c     | 130
> ++++++++++++++++++++++++++++++++++
>  lib/utils/reset/fdt_reset_thead.h     |  23 ++++++
>  lib/utils/reset/fdt_reset_thead_asm.S |  47 ++++++++++++
>  lib/utils/reset/objects.mk            |   2 +
>  7 files changed, 212 insertions(+)
>  create mode 100644 lib/utils/reset/fdt_reset_thead.c  create mode 100644
> lib/utils/reset/fdt_reset_thead.h  create mode 100644
> lib/utils/reset/fdt_reset_thead_asm.S
> 
> diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h index
> 9fa0fe5..1ff36de 100644
> --- a/include/sbi/riscv_asm.h
> +++ b/include/sbi/riscv_asm.h
> @@ -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))
> 
> diff --git a/include/sbi/riscv_barrier.h b/include/sbi/riscv_barrier.h index
> 905ecb4..1fba8b8 100644
> --- a/include/sbi/riscv_barrier.h
> +++ b/include/sbi/riscv_barrier.h
> @@ -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)
> 
> diff --git a/lib/utils/reset/fdt_reset.c b/lib/utils/reset/fdt_reset.c index
> dead8a3..82532c2 100644
> --- a/lib/utils/reset/fdt_reset.c
> +++ b/lib/utils/reset/fdt_reset.c
> @@ -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; diff --git
> a/lib/utils/reset/fdt_reset_thead.c b/lib/utils/reset/fdt_reset_thead.c
> new file mode 100644
> index 0000000..cce0141
> --- /dev/null
> +++ b/lib/utils/reset/fdt_reset_thead.c
> @@ -0,0 +1,130 @@
> +/*
> + * 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 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 *)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, (u64)&__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 *)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++) {
> +				writel((u64)(&__thead_pre_start_warm), p +
> 8*i);
> +				writel((u64)(&__thead_pre_start_warm) >>
> 32, p + 8*i + 4);
> +			}
> +		}
> +
> +		val = fdt_getprop(fdt, nodeoff, "control-reg", &len);
> +		if (len > 0 && val) {
> +			p = (void *)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
> +};
> diff --git a/lib/utils/reset/fdt_reset_thead.h
> b/lib/utils/reset/fdt_reset_thead.h
> new file mode 100644
> index 0000000..d7a686e
> --- /dev/null
> +++ b/lib/utils/reset/fdt_reset_thead.h
> @@ -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__ */
> diff --git a/lib/utils/reset/fdt_reset_thead_asm.S
> b/lib/utils/reset/fdt_reset_thead_asm.S
> new file mode 100644
> index 0000000..8237951
> --- /dev/null
> +++ b/lib/utils/reset/fdt_reset_thead_asm.S
> @@ -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
> diff --git a/lib/utils/reset/objects.mk b/lib/utils/reset/objects.mk index
> b447261..b6619f4 100644
> --- a/lib/utils/reset/objects.mk
> +++ b/lib/utils/reset/objects.mk
> @@ -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
> --
> 2.7.4




More information about the opensbi mailing list