riscv: Implement riscv_get_time() API using rdtime instruction
authorAnup Patel <anup@brainfault.org>
Wed, 12 Dec 2018 14:12:31 +0000 (06:12 -0800)
committerAndes <uboot@andestech.com>
Tue, 18 Dec 2018 01:56:27 +0000 (09:56 +0800)
This adds an implementation of riscv_get_time() API that is using
rdtime instruction.

This is the case for S-mode U-Boot, and is useful for processors
that support rdtime in M-mode too.

Signed-off-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
arch/riscv/Kconfig
arch/riscv/lib/Makefile
arch/riscv/lib/rdtime.c [new file with mode: 0644]

index f513f52672bae0ce08ff9385a7db156078cbee0a..7dc6e3fad2e7dc09f9370e849bfe29d59ddd83ca 100644 (file)
@@ -104,4 +104,12 @@ config SIFIVE_CLINT
          The SiFive CLINT block holds memory-mapped control and status registers
          associated with software and timer interrupts.
 
+config RISCV_RDTIME
+       bool
+       default y if RISCV_SMODE
+       help
+         The provides the riscv_get_time() API that is implemented using the
+         standard rdtime instruction. This is the case for S-mode U-Boot, and
+         is useful for processors that support rdtime in M-mode too.
+
 endmenu
index b13c87661e18a02fe5465895a1326c43a0f2bd23..edfa61690c7db86c8dac8d4bfca08d48097ef5d0 100644 (file)
@@ -9,6 +9,7 @@
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-$(CONFIG_CMD_GO) += boot.o
 obj-y  += cache.o
+obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
 obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
 obj-y  += interrupts.o
 obj-y  += reset.o
diff --git a/arch/riscv/lib/rdtime.c b/arch/riscv/lib/rdtime.c
new file mode 100644 (file)
index 0000000..e128d7f
--- /dev/null
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Anup Patel <anup@brainfault.org>
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * The riscv_get_time() API implementation that is using the
+ * standard rdtime instruction.
+ */
+
+#include <common.h>
+
+/* Implement the API required by RISC-V timer driver */
+int riscv_get_time(u64 *time)
+{
+#ifdef CONFIG_64BIT
+       u64 n;
+
+       __asm__ __volatile__ (
+               "rdtime %0"
+               : "=r" (n));
+
+       *time = n;
+#else
+       u32 lo, hi, tmp;
+
+       __asm__ __volatile__ (
+               "1:\n"
+               "rdtimeh %0\n"
+               "rdtime %1\n"
+               "rdtimeh %2\n"
+               "bne %0, %2, 1b"
+               : "=&r" (hi), "=&r" (lo), "=&r" (tmp));
+
+       *time = ((u64)hi << 32) | lo;
+#endif
+
+       return 0;
+}