[PATCH v2 2/2] lib: utils: reset: Add T-HEAD sample platform reset driver
Guo Ren
guoren at kernel.org
Wed Apr 21 08:42:58 BST 2021
Thx Anup,
On Wed, Apr 21, 2021 at 12:30 PM Anup Patel <Anup.Patel at wdc.com> wrote:
>
>
>
> > -----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.
Okay, and I'll clean up the platform/thead and update the document.
>
> 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
>
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
More information about the opensbi
mailing list