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

Guo Ren guoren at kernel.org
Sat Apr 17 11:30:05 BST 2021


ping kindly ... Any problems with the patch, please let me know.

On Tue, Apr 13, 2021 at 11:45 AM <guoren at kernel.org> wrote:
>
> 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.
>
> Signed-off-by: Guo Ren <guoren at linux.alibaba.com>
> 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>
> ---
>  lib/utils/reset/fdt_reset.c           |   2 +
>  lib/utils/reset/fdt_reset_thead.c     | 117 ++++++++++++++++++++++++++++++++++
>  lib/utils/reset/fdt_reset_thead.h     |  25 ++++++++
>  lib/utils/reset/fdt_reset_thead_asm.S |  47 ++++++++++++++
>  lib/utils/reset/objects.mk            |   2 +
>  5 files changed, 193 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/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..12eb1fc
> --- /dev/null
> +++ b/lib/utils/reset/fdt_reset_thead.c
> @@ -0,0 +1,117 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + */
> +
> +#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();
> +
> +               __asm__ __volatile__("fence.i\n":::"memory");
> +
> +               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;
> +}
> +
> +void thead_system_reset(u32 type, u32 reason)
> +{
> +       __asm__ __volatile__("ebreak\n");
> +}
> +
> +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 = 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..dbd76ad
> --- /dev/null
> +++ b/lib/utils/reset/fdt_reset_thead.h
> @@ -0,0 +1,25 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + */
> +
> +#define MAX_CUSTOM_CSR 32
> +
> +#ifndef __ASSEMBLER__
> +#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>
> +
> +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
> 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