riscv: Rework riscv timer driver to only support S-mode

The riscv-timer driver currently serves as a shim for several riscv timer
drivers. This is not too desirable because it bypasses the usual timer
selection via the driver model. There is no easy way to specify an
alternate timing driver, or have the tick rate depend on the cpu's
configured frequency. The timer drivers also do not have device structs,
and so have to rely on storing parameters in gd_t. Lastly, there is no
initialization call, so driver init is done in the same function which
reads the time. This can result in confusing error messages. To a user, it
looks like the driver failed when trying to read the time, whereas it may
have failed while initializing.

This patch removes the shim functionality from the riscv-timer driver, and
has it instead implement the former rdtime.c timer driver. This is because
existing u-boot users who pass in a device tree (e.g. qemu) do not create a
timer device for S-mode u-boot. The existing behavior of creating the
riscv-timer device in the riscv cpu driver must be kept. The actual reading
of the CSRs has been redone in the style of Linux's get_cycles64.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
Reviewed-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Rick Chen <rick@andestech.com>
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 6370244..d40d313 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -146,8 +146,8 @@
 	bool "RISC-V timer support"
 	depends on TIMER && RISCV
 	help
-	  Select this to enable support for the timer as defined
-	  by the RISC-V privileged architecture spec.
+	  Select this to enable support for a generic RISC-V S-Mode timer
+	  driver.
 
 config ROCKCHIP_TIMER
 	bool "Rockchip timer support"
diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
index 9f9f070..449fcfc 100644
--- a/drivers/timer/riscv_timer.c
+++ b/drivers/timer/riscv_timer.c
@@ -1,36 +1,37 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
+ * Copyright (C) 2020, Sean Anderson <seanga2@gmail.com>
  * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright (C) 2018, Anup Patel <anup@brainfault.org>
+ * Copyright (C) 2012 Regents of the University of California
  *
- * RISC-V privileged architecture defined generic timer driver
+ * RISC-V architecturally-defined generic timer driver
  *
- * This driver relies on RISC-V platform codes to provide the essential API
- * riscv_get_time() which is supposed to return the timer counter as defined
- * by the RISC-V privileged architecture spec.
- *
- * This driver can be used in both M-mode and S-mode U-Boot.
+ * This driver provides generic timer support for S-mode U-Boot.
  */
 
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
 #include <timer.h>
-#include <asm/io.h>
-
-/**
- * riscv_get_time() - get the timer counter
- *
- * Platform codes should provide this API in order to make this driver function.
- *
- * @time:	the 64-bit timer count  as defined by the RISC-V privileged
- *		architecture spec.
- * @return:	0 on success, -ve on error.
- */
-extern int riscv_get_time(u64 *time);
+#include <asm/csr.h>
 
 static int riscv_timer_get_count(struct udevice *dev, u64 *count)
 {
-	return riscv_get_time(count);
+	if (IS_ENABLED(CONFIG_64BIT)) {
+		*count = csr_read(CSR_TIME);
+	} else {
+		u32 hi, lo;
+
+		do {
+			hi = csr_read(CSR_TIMEH);
+			lo = csr_read(CSR_TIME);
+		} while (hi != csr_read(CSR_TIMEH));
+
+		*count = ((u64)hi << 32) | lo;
+	}
+
+	return 0;
 }
 
 static int riscv_timer_probe(struct udevice *dev)