arm64: Add ARCH Timer

SoC sdm845 uses ARCH Timer

Change-Id: I45e2d4d2c16a2cded3df20d393d2b8820050ac80
Signed-off-by: T Michael Turney <mturney@codeaurora.org>
Reviewed-on: https://review.coreboot.org/25612
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
diff --git a/src/arch/arm64/Kconfig b/src/arch/arm64/Kconfig
index 4f4b33b..cae558b 100644
--- a/src/arch/arm64/Kconfig
+++ b/src/arch/arm64/Kconfig
@@ -22,6 +22,10 @@
 
 source src/arch/arm64/armv8/Kconfig
 
+config ARM64_USE_ARCH_TIMER
+	bool
+	default n
+
 config ARM64_USE_ARM_TRUSTED_FIRMWARE
 	bool
 	default n
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc
index d9a73bd..997c2da 100644
--- a/src/arch/arm64/Makefile.inc
+++ b/src/arch/arm64/Makefile.inc
@@ -45,6 +45,7 @@
 
 bootblock-y += boot.c
 bootblock-y += eabi_compat.c
+bootblock-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
 bootblock-y += transition.c transition_asm.S
 
 bootblock-y += memset.S
@@ -72,6 +73,7 @@
 verstage-y += boot.c
 verstage-y += div0.c
 verstage-y += eabi_compat.c
+verstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
 verstage-y += memset.S
 verstage-y += memcpy.S
 verstage-y += memmove.S
@@ -89,6 +91,7 @@
 romstage-y += boot.c
 romstage-y += div0.c
 romstage-y += eabi_compat.c
+romstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
 romstage-y += memset.S
 romstage-y += memcpy.S
 romstage-y += memmove.S
@@ -115,6 +118,7 @@
 ramstage-y += eabi_compat.c
 ramstage-y += boot.c
 ramstage-y += tables.c
+ramstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
 ramstage-y += memset.S
 ramstage-y += memcpy.S
 ramstage-y += memmove.S
@@ -125,6 +129,7 @@
 rmodules_arm64-y += memcpy.S
 rmodules_arm64-y += memmove.S
 rmodules_arm64-y += eabi_compat.c
+rmodules_arm64-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
 
 ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c)
 
diff --git a/src/arch/arm64/arch_timer.c b/src/arch/arm64/arch_timer.c
new file mode 100644
index 0000000..e7f3732
--- /dev/null
+++ b/src/arch/arm64/arch_timer.c
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2018, The Linux Foundation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <timer.h>
+#include <arch/lib_helpers.h>
+
+void timer_monotonic_get(struct mono_time *mt)
+{
+	uint64_t tvalue = raw_read_cntpct_el0();
+	uint32_t tfreq  = raw_read_cntfrq_el0();
+	long usecs = (tvalue * 1000000) / tfreq;
+	mono_time_set_usecs(mt, usecs);
+}
diff --git a/src/arch/arm64/armv8/lib/sysctrl.c b/src/arch/arm64/armv8/lib/sysctrl.c
index 9cf26a5..ef3b455 100644
--- a/src/arch/arm64/armv8/lib/sysctrl.c
+++ b/src/arch/arm64/armv8/lib/sysctrl.c
@@ -1059,3 +1059,11 @@
 {
 	__asm__ __volatile__("msr CNTFRQ_EL0, %0\n\t" : : "r" ((uint64_t)cntfrq_el0) : "memory");
 }
+
+uint64_t raw_read_cntpct_el0(void)
+{
+	uint64_t cntpct_el0;
+
+	__asm__ __volatile__("mrs %0, CNTPCT_EL0\n\t" : "=r" (cntpct_el0) : : "memory");
+	return cntpct_el0;
+}
diff --git a/src/arch/arm64/include/armv8/arch/lib_helpers.h b/src/arch/arm64/include/armv8/arch/lib_helpers.h
index 94078e9..19bb18d 100644
--- a/src/arch/arm64/include/armv8/arch/lib_helpers.h
+++ b/src/arch/arm64/include/armv8/arch/lib_helpers.h
@@ -557,6 +557,7 @@
 void raw_write_vbar(uint64_t vbar, uint32_t el);
 uint32_t raw_read_cntfrq_el0(void);
 void raw_write_cntfrq_el0(uint32_t cntfrq_el0);
+uint64_t raw_read_cntpct_el0(void);
 
 /* Cache maintenance system instructions */
 void dccisw(uint64_t cisw);