summaryrefslogtreecommitdiff
path: root/chip/ish/hwtimer.c
diff options
context:
space:
mode:
authorJaiber John <jaiber.j.john@intel.com>2016-03-31 23:49:53 +0530
committerchrome-bot <chrome-bot@chromium.org>2016-11-04 18:31:29 -0700
commitd7b938f857755a6a9a7ffbe9f281a14821675a9f (patch)
tree829973af641af0124b847871248e7a9b4027456a /chip/ish/hwtimer.c
parentcbae8f9b321f33734a34cb85c82636bbfa7663ee (diff)
downloadchrome-ec-d7b938f857755a6a9a7ffbe9f281a14821675a9f.tar.gz
ish: Add support for ISH chip
This patch adds the initial support for ISH chip to enable the EC firmware to boot on Intel Integrated Sensor Hub (ISH). The following are enabled: 1. Inter-Processor Communication (IPC) driver that enables the ISH to communicate with the host Operating system via shared registers. 2. High Precision Event Timer (HPET) driver that provides configurable timers for the FW to use in task scheduling. 3. I2C bus driver for accessing sensors. 4. UART console driver with TX support only. BUG=chrome-os-partner:51851 BRANCH=None TEST=`make buildall -j` Change-Id: I15d4c201b799cfa79bed220ee573b75f5cd7b1f7 Signed-off-by: Jaiber John <jaiber.j.john@intel.com> Signed-off-by: Alex Brill <alexander.brill@intel.com> Signed-off-by: Gomathi Kumar <gomathi.kumar@intel.com> Reviewed-on: https://chromium-review.googlesource.com/336710 Commit-Ready: Raj Mojumder <raj.mojumder@intel.com> Tested-by: Jaiber J John <jaiber.j.john@intel.com> Tested-by: Raj Mojumder <raj.mojumder@intel.com> Reviewed-by: Jaiber J John <jaiber.j.john@intel.com> Reviewed-by: Raj Mojumder <raj.mojumder@intel.com> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'chip/ish/hwtimer.c')
-rw-r--r--chip/ish/hwtimer.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/chip/ish/hwtimer.c b/chip/ish/hwtimer.c
new file mode 100644
index 0000000000..13c07decd2
--- /dev/null
+++ b/chip/ish/hwtimer.c
@@ -0,0 +1,129 @@
+/* Copyright (c) 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Hardware timers driver - HPET */
+
+#include "hpet.h"
+#include "hwtimer.h"
+#include "registers.h"
+#include "task.h"
+
+#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
+#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args)
+
+void __hw_clock_event_set(uint32_t deadline)
+{
+ HPET_TIMER_COMP(1) = HPET_MAIN_COUNTER + deadline;
+ HPET_TIMER_CONF_CAP(1) |= HPET_Tn_INT_ENB_CNF;
+}
+
+uint32_t __hw_clock_event_get(void)
+{
+ return 0;
+}
+
+void __hw_clock_event_clear(void)
+{
+ HPET_TIMER_CONF_CAP(1) &= ~HPET_Tn_INT_ENB_CNF;
+}
+
+uint32_t __hw_clock_source_read(void)
+{
+ return HPET_MAIN_COUNTER;
+}
+
+void __hw_clock_source_set(uint32_t ts)
+{
+ HPET_GENERAL_CONFIG &= ~HPET_ENABLE_CNF;
+ HPET_MAIN_COUNTER = 0x00;
+
+ while (HPET_CTRL_STATUS & HPET_GEN_CONF_STATUS_BIT)
+ ;
+
+ HPET_GENERAL_CONFIG |= HPET_ENABLE_CNF;
+}
+
+static void __hw_clock_source_irq(int timer_id)
+{
+ /* Clear interrupt */
+ HPET_INTR_CLEAR = (1 << timer_id);
+
+ /* If IRQ is from timer 0, 32-bit timer overflowed */
+ process_timers(timer_id == 0);
+}
+
+void __hw_clock_source_irq_0(void)
+{
+ __hw_clock_source_irq(0);
+}
+DECLARE_IRQ(ISH_HPET_TIMER0_IRQ, __hw_clock_source_irq_0);
+
+void __hw_clock_source_irq_1(void)
+{
+ __hw_clock_source_irq(1);
+}
+DECLARE_IRQ(ISH_HPET_TIMER1_IRQ, __hw_clock_source_irq_1);
+
+int __hw_clock_source_init(uint32_t start_t)
+{
+
+ /*
+ * The timer can only fire interrupt when its value reaches zero.
+ * Therefore we need two timers:
+ * - Timer 0 as free running timer
+ * - Timer 1 as event timer
+ */
+
+ /* Disable HPET */
+ HPET_GENERAL_CONFIG &= ~HPET_ENABLE_CNF;
+ HPET_MAIN_COUNTER = 0x00;
+
+ /* Set comparator value */
+ HPET_TIMER_COMP(0) = ISH_HPET_CLK_FREQ / ISH_TICKS_PER_SEC;
+
+ /* Wait for timer to settle */
+ while (HPET_CTRL_STATUS & HPET_GEN_CONF_STATUS_BIT)
+ ;
+
+ /* Timer 0 - enable periodic mode */
+ HPET_TIMER_CONF_CAP(0) |= HPET_Tn_TYPE_CNF;
+ HPET_TIMER_CONF_CAP(0) |= HPET_Tn_32MODE_CNF;
+
+ while (HPET_CTRL_STATUS & HPET_T0_CONF_CAP_BIT)
+ ;
+
+ /* Set IRQ routing */
+#if ISH_HPET_TIMER0_IRQ < 32
+ HPET_TIMER_CONF_CAP(0) &= ~HPET_Tn_INT_ROUTE_CNF_MASK;
+ HPET_TIMER_CONF_CAP(0) |= (ISH_HPET_TIMER0_IRQ <<
+ HPET_Tn_INT_ROUTE_CNF_SHIFT);
+#else
+ HPET_TIMER_CONF_CAP(0) &= ~HPET_Tn_INT_ROUTE_CNF_MASK;
+#endif
+
+ while (HPET_CTRL_STATUS & HPET_T0_CONF_CAP_BIT)
+ ;
+
+ /* Level interrupt */
+ HPET_TIMER_CONF_CAP(0) |= HPET_Tn_INT_TYPE_CNF;
+ HPET_TIMER_CONF_CAP(1) |= HPET_Tn_INT_TYPE_CNF;
+
+ /* Unask HPET IRQ in IOAPIC */
+ task_enable_irq(ISH_HPET_TIMER0_IRQ);
+ task_enable_irq(ISH_HPET_TIMER1_IRQ);
+
+ /* Enable interrupt */
+ HPET_TIMER_CONF_CAP(0) |= HPET_Tn_INT_ENB_CNF;
+ HPET_TIMER_CONF_CAP(1) |= HPET_Tn_INT_ENB_CNF;
+
+ while (HPET_CTRL_STATUS & HPET_T0_CONF_CAP_BIT)
+ ;
+
+ /* Enable HPET main counter */
+ HPET_GENERAL_CONFIG |= HPET_ENABLE_CNF;
+
+ return ISH_HPET_TIMER1_IRQ; /* One shot */
+}