[U-Boot] [PATCH 05/19] riscv: Add a SYSCON driver for Core Local Interruptor
Philipp Tomsich
philipp.tomsich at theobroma-systems.com
Thu Dec 6 14:33:42 UTC 2018
> On 13.11.2018, at 09:21, Bin Meng <bmeng.cn at gmail.com> wrote:
>
> This adds U-Boot syscon driver for RISC-V Core Local Interruptor
> (CLINT). The CLINT block holds memory-mapped control and status
> registers associated with software and timer interrupts.
>
> 3 APIs are provided for U-Boot to implement Supervisor Binary
> Interface (SBI) as defined by the RISC-V privileged architecture
> spec v1.10.
>
> Signed-off-by: Bin Meng <bmeng.cn at gmail.com>
> ---
>
> arch/riscv/Kconfig | 8 +++++
> arch/riscv/include/asm/clint.h | 24 +++++++++++++++
> arch/riscv/lib/Makefile | 1 +
> arch/riscv/lib/clint.c | 69 ++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 102 insertions(+)
> create mode 100644 arch/riscv/include/asm/clint.h
> create mode 100644 arch/riscv/lib/clint.c
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index a37e895..abfc083 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -73,4 +73,12 @@ config 32BIT
> config 64BIT
> bool
>
> +config RISCV_CLINT
> + bool "Support Core Local Interruptor (CLINT)"
> + select REGMAP
> + select SYSCON
> + help
> + The CLINT block holds memory-mapped control and status registers
> + associated with software and timer interrupts.
> +
> endmenu
> diff --git a/arch/riscv/include/asm/clint.h b/arch/riscv/include/asm/clint.h
> new file mode 100644
> index 0000000..1c6024f
> --- /dev/null
> +++ b/arch/riscv/include/asm/clint.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2018, Bin Meng <bmeng.cn at gmail.com>
> + */
> +
> +#ifndef _ASM_RISCV_CLINT_H
> +#define _ASM_RISCV_CLINT_H
> +
> +/*
> + * System controllers in a RISC-V system
> + *
> + * So far only Core Local Interruptor (CLINT) is defined. If new system
> + * controller is added, we may need move the defines to somewhere else.
> + */
> +enum {
> + RISCV_NONE,
> + RISCV_SYSCON_CLINT, /* Core Local Interruptor (CLINT) */
> +};
> +
> +void riscv_send_ipi(int hart);
> +void riscv_set_timecmp(int hart, u64 cmp);
> +u64 riscv_get_time(void);
> +
> +#endif /* _ASM_RISCV_CLINT_H */
> diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
> index b58db89..b5a77c2 100644
> --- a/arch/riscv/lib/Makefile
> +++ b/arch/riscv/lib/Makefile
> @@ -9,6 +9,7 @@
> obj-$(CONFIG_CMD_BOOTM) += bootm.o
> obj-$(CONFIG_CMD_GO) += boot.o
> obj-y += cache.o
> +obj-$(CONFIG_RISCV_CLINT) += clint.o
> obj-y += interrupts.o
> obj-y += reset.o
> obj-y += setjmp.o
> diff --git a/arch/riscv/lib/clint.c b/arch/riscv/lib/clint.c
> new file mode 100644
> index 0000000..369aa1d
> --- /dev/null
> +++ b/arch/riscv/lib/clint.c
> @@ -0,0 +1,69 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018, Bin Meng <bmeng.cn at gmail.com>
> + *
> + * U-Boot syscon driver for RISC-V Core Local Interruptor (CLINT)
> + * The CLINT block holds memory-mapped control and status registers
> + * associated with software and timer interrupts.
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <regmap.h>
> +#include <syscon.h>
> +#include <asm/clint.h>
> +#include <asm/io.h>
> +
> +/* MSIP registers */
> +#define MSIP_REG(base, hart) ((ulong)(base) + (hart) * 4)
> +/* Timer compare register */
> +#define MTIMECMP_REG(base, hart) ((ulong)(base) + 0x4000 + (hart) * 8)
> +/* Timer register */
> +#define MTIME_REG(base) ((ulong)(base) + 0xbff8)
> +
> +static void __iomem *clint_base;
> +
> +/*
> + * The following 3 APIs are used to implement Supervisor Binary Interface (SBI)
> + * as defined by the RISC-V privileged architecture spec v1.10.
> + *
> + * For performance reasons we don't want to get the CLINT register base via
> + * syscon_get_first_range() each time we enter in those functions, instead
> + * the base address was saved to a global variable during the clint driver
> + * probe phase, so that we can use it directly.
> + */
> +
> +void riscv_send_ipi(int hart)
> +{
> + writel(1, (void __iomem *)MSIP_REG(clint_base, hart));
> +}
> +
> +void riscv_set_timecmp(int hart, u64 cmp)
> +{
> + writeq(cmp, (void __iomem *)MTIMECMP_REG(clint_base, hart));
> +}
> +
> +u64 riscv_get_time(void)
> +{
> + return readq((void __iomem *)MTIME_REG(clint_base));
> +}
> +
> +static int clint_probe(struct udevice *dev)
> +{
> + clint_base = syscon_get_first_range(RISCV_SYSCON_CLINT);
> +
> + return 0;
> +}
> +
> +static const struct udevice_id clint_ids[] = {
> + { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT },
> + { }
> +};
> +
> +U_BOOT_DRIVER(riscv_clint) = {
> + .name = "riscv_clint",
> + .id = UCLASS_SYSCON,
Wouldn’t a separate UCLASS be more appropriate?
> + .of_match = clint_ids,
> + .probe = clint_probe,
> + .flags = DM_FLAG_PRE_RELOC,
> +};
> --
> 2.7.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
More information about the U-Boot
mailing list