Trusted Firmware-A Tests, version 2.0

This is the first public version of the tests for the Trusted
Firmware-A project. Please see the documentation provided in the
source tree for more details.

Change-Id: I6f3452046a1351ac94a71b3525c30a4ca8db7867
Signed-off-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
Co-authored-by: amobal01 <amol.balasokamble@arm.com>
Co-authored-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Co-authored-by: Asha R <asha.r@arm.com>
Co-authored-by: Chandni Cherukuri <chandni.cherukuri@arm.com>
Co-authored-by: David Cunado <david.cunado@arm.com>
Co-authored-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
Co-authored-by: Douglas Raillard <douglas.raillard@arm.com>
Co-authored-by: dp-arm <dimitris.papastamos@arm.com>
Co-authored-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Co-authored-by: Jonathan Wright <jonathan.wright@arm.com>
Co-authored-by: Kévin Petit <kevin.petit@arm.com>
Co-authored-by: Roberto Vargas <roberto.vargas@arm.com>
Co-authored-by: Sathees Balya <sathees.balya@arm.com>
Co-authored-by: Shawon Roy <Shawon.Roy@arm.com>
Co-authored-by: Soby Mathew <soby.mathew@arm.com>
Co-authored-by: Thomas Abraham <thomas.abraham@arm.com>
Co-authored-by: Vikram Kanigiri <vikram.kanigiri@arm.com>
Co-authored-by: Yatharth Kochar <yatharth.kochar@arm.com>
diff --git a/drivers/arm/timer/private_timer.c b/drivers/arm/timer/private_timer.c
new file mode 100644
index 0000000..c629448
--- /dev/null
+++ b/drivers/arm/timer/private_timer.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <platform.h>
+
+/*******************************************************************************
+ * Data structure to keep track of per-cpu secure generic timer context across
+ * power management operations.
+ ******************************************************************************/
+typedef struct timer_context {
+	uint64_t cval;
+	uint32_t ctl;
+} timer_context_t;
+
+static timer_context_t pcpu_timer_context[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * This function initializes the generic timer to fire every `timeo` ms.
+ ******************************************************************************/
+void private_timer_start(unsigned long timeo)
+{
+	uint64_t cval, freq;
+	uint32_t ctl = 0;
+
+	/* Any previous pending timer activation will be disabled. */
+	cval = read_cntpct_el0();
+	freq = read_cntfrq_el0();
+	cval += (freq * timeo) / 1000;
+	write_cnthp_cval_el2(cval);
+
+	/* Enable the secure physical timer */
+	set_cntp_ctl_enable(ctl);
+	write_cnthp_ctl_el2(ctl);
+}
+
+/*******************************************************************************
+ * This function deasserts the timer interrupt prior to cpu power down
+ ******************************************************************************/
+void private_timer_stop(void)
+{
+	/* Disable the timer */
+	write_cnthp_ctl_el2(0);
+}
+
+/*******************************************************************************
+ * This function saves the timer context prior to cpu suspension
+ ******************************************************************************/
+void private_timer_save(void)
+{
+	uint32_t linear_id = platform_get_core_pos(read_mpidr_el1());
+
+	pcpu_timer_context[linear_id].cval = read_cnthp_cval_el2();
+	pcpu_timer_context[linear_id].ctl = read_cnthp_ctl_el2();
+	flush_dcache_range((uintptr_t) &pcpu_timer_context[linear_id],
+			   sizeof(pcpu_timer_context[linear_id]));
+}
+
+/*******************************************************************************
+ * This function restores the timer context post cpu resummption
+ ******************************************************************************/
+void private_timer_restore(void)
+{
+	uint32_t linear_id = platform_get_core_pos(read_mpidr_el1());
+
+	write_cnthp_cval_el2(pcpu_timer_context[linear_id].cval);
+	write_cnthp_ctl_el2(pcpu_timer_context[linear_id].ctl);
+}
diff --git a/drivers/arm/timer/sp804.c b/drivers/arm/timer/sp804.c
new file mode 100644
index 0000000..de88cda
--- /dev/null
+++ b/drivers/arm/timer/sp804.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <gic_v2.h>
+#include <mmio.h>
+#include <sp804.h>
+
+static unsigned int sp804_freq;
+static uintptr_t sp804_base;
+
+int sp804_timer_program(unsigned long time_out_ms)
+{
+	unsigned int load_val;
+	unsigned char ctrl_reg;
+
+	assert(sp804_base);
+	assert(time_out_ms);
+
+	/* Disable the timer */
+	ctrl_reg = mmio_read_8(sp804_base + SP804_CTRL_OFFSET);
+	ctrl_reg &= ~(TIMER_EN | INT_ENABLE);
+	mmio_write_8(sp804_base + SP804_CTRL_OFFSET, ctrl_reg);
+
+	/* Calculate the load value */
+	load_val = (sp804_freq * time_out_ms) / 1000;
+
+	/* Write the load value to sp804 timer */
+	mmio_write_32(sp804_base + SP804_LOAD_OFFSET, load_val);
+
+	/* Enable the timer */
+	ctrl_reg |= (TIMER_EN | INT_ENABLE);
+	mmio_write_8(sp804_base + SP804_CTRL_OFFSET, ctrl_reg);
+
+	return 0;
+}
+
+static void sp804_timer_disable(void)
+{
+	unsigned char ctrl_reg;
+
+	/*
+	 * The interrupt line should be cleared prior to timer disable.
+	 * Otherwise the interrupt line level decay from high to quiescent
+	 * level is not quick enough which may trigger spurious interrupt.
+	 * Write a dummy load value to sp804 timer to clear the interrupt.
+	 */
+	mmio_write_32(sp804_base + SP804_LOAD_OFFSET, 0xffff);
+
+	/* De-assert the timer interrupt */
+	mmio_write_8(sp804_base + SP804_INT_CLR_OFFSET, 0x0);
+
+	/* Disable the timer */
+	ctrl_reg = mmio_read_8(sp804_base + SP804_CTRL_OFFSET);
+	ctrl_reg &= ~(TIMER_EN | INT_ENABLE);
+	mmio_write_8(sp804_base + SP804_CTRL_OFFSET, ctrl_reg);
+}
+
+int sp804_timer_cancel(void)
+{
+	assert(sp804_base);
+	sp804_timer_disable();
+	return 0;
+}
+
+int sp804_timer_handler(void)
+{
+	assert(sp804_base);
+	sp804_timer_disable();
+	return 0;
+}
+
+int sp804_timer_init(uintptr_t base_addr, unsigned int timer_freq)
+{
+	unsigned char ctrl_reg;
+
+	/* Check input parameters */
+	assert(base_addr && timer_freq);
+
+	/* Check for duplicate initialization */
+	assert(sp804_base == 0);
+
+	sp804_base = base_addr;
+	sp804_freq = timer_freq;
+
+	/*
+	 * Configure the timer in one shot mode, pre-scalar divider to 1,
+	 * timer counter width to 32 bits and un-mask the interrupt.
+	 */
+	ctrl_reg = ONESHOT_MODE | TIMER_PRE_DIV1 | TIMER_SIZE;
+	mmio_write_8(sp804_base + SP804_CTRL_OFFSET, ctrl_reg);
+
+	return 0;
+}
diff --git a/drivers/arm/timer/system_timer.c b/drivers/arm/timer/system_timer.c
new file mode 100644
index 0000000..3415e41
--- /dev/null
+++ b/drivers/arm/timer/system_timer.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <debug.h>
+#include <gic_v2.h>
+#include <irq.h>
+#include <mmio.h>
+#include <system_timer.h>
+
+static uintptr_t g_systimer_base;
+
+int program_systimer(unsigned long time_out_ms)
+{
+	unsigned int cntp_ctl;
+	unsigned long long count_val;
+	unsigned int freq;
+
+	/* Check timer base is initialised */
+	assert(g_systimer_base);
+
+	count_val = mmio_read_64(g_systimer_base + CNTPCT_LO);
+	freq = read_cntfrq_el0();
+	count_val += (freq * time_out_ms) / 1000;
+	mmio_write_64(g_systimer_base + CNTP_CVAL_LO, count_val);
+
+	/* Enable the timer */
+	cntp_ctl = mmio_read_32(g_systimer_base + CNTP_CTL);
+	set_cntp_ctl_enable(cntp_ctl);
+	clr_cntp_ctl_imask(cntp_ctl);
+	mmio_write_32(g_systimer_base + CNTP_CTL, cntp_ctl);
+
+	/*
+	 * Ensure that we have programmed a timer interrupt for a time in
+	 * future. Else we will have to wait for the systimer to rollover
+	 * for the interrupt to fire (which is 64 years).
+	 */
+	if (count_val < mmio_read_64(g_systimer_base + CNTPCT_LO))
+		panic();
+
+	VERBOSE("%s : interrupt requested at sys_counter: %lld "
+		"time_out_ms: %ld\n", __func__, count_val, time_out_ms);
+
+	return 0;
+}
+
+static void disable_systimer(void)
+{
+	uint32_t val;
+
+	/* Check timer base is initialised */
+	assert(g_systimer_base);
+
+	/* Deassert and disable the timer interrupt */
+	val = 0;
+	set_cntp_ctl_imask(val);
+	mmio_write_32(g_systimer_base + CNTP_CTL, val);
+}
+
+int cancel_systimer(void)
+{
+	disable_systimer();
+	return 0;
+}
+
+int handler_systimer(void)
+{
+	disable_systimer();
+	return 0;
+}
+
+int init_systimer(uintptr_t systimer_base)
+{
+	/* Check timer base is not initialised */
+	assert(!g_systimer_base);
+
+	g_systimer_base = systimer_base;
+
+	/* Disable the timer as the reset value is unknown */
+	disable_systimer();
+
+	/* Initialise CVAL to zero */
+	mmio_write_64(g_systimer_base + CNTP_CVAL_LO, 0);
+
+	return 0;
+}