summaryrefslogtreecommitdiff
path: root/drivers/arm
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2015-10-01 16:35:47 +0100
committerSoby Mathew <soby.mathew@arm.com>2015-10-27 15:16:39 +0000
commite8f96b5986caea2563e97f0115848a57aa839047 (patch)
treebc7d028892282e882be679d74f0ef420136665be /drivers/arm
parenta91e03bf4d65d679534046d29f85fa343269338b (diff)
Add ARM SP804 timer in TFTF
This patch adds driver for SP804 timer peripheral and it configures it in one shot mode for the timer framework. It also modifies juno platform layer to use Motherboard SP804 peripheral for timer framework. Change-Id: I39a55bf2d84d7f44b539ccf747a7c30a4edd1e7d
Diffstat (limited to 'drivers/arm')
-rw-r--r--drivers/arm/timer/sp804.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/arm/timer/sp804.c b/drivers/arm/timer/sp804.c
new file mode 100644
index 0000000..f0a9dcc
--- /dev/null
+++ b/drivers/arm/timer/sp804.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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);
+ 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;
+ mmio_write_8(sp804_base + SP804_CTRL_OFFSET, ctrl_reg);
+
+ return 0;
+}
+
+static void sp804_timer_disable(void)
+{
+ unsigned char ctrl_reg;
+
+ /* Disable the timer */
+ ctrl_reg = mmio_read_8(sp804_base + SP804_CTRL_OFFSET);
+ ctrl_reg &= (~TIMER_EN);
+ mmio_write_8(sp804_base + SP804_CTRL_OFFSET, ctrl_reg);
+
+ /* De-assert the timer interrupt */
+ mmio_write_8(sp804_base + SP804_INT_CLR_OFFSET, 0x0);
+}
+
+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 | INT_ENABLE | TIMER_PRE_DIV1 | TIMER_SIZE;
+ mmio_write_8(sp804_base + SP804_CTRL_OFFSET, ctrl_reg);
+
+ return 0;
+}