summaryrefslogtreecommitdiff
path: root/chip/mchp/watchdog.c
diff options
context:
space:
mode:
authorScott Worley <scott.worley@microchip.corp-partner.google.com>2017-12-21 14:49:50 -0500
committerchrome-bot <chrome-bot@chromium.org>2017-12-28 14:50:32 -0800
commitc56df0d8314358709ef58f2dd82a858d62e30866 (patch)
tree85635ded5457962fb9ad63353abf86d68c695ece /chip/mchp/watchdog.c
parentf8dc4617128f72cdcef4aae33afd665d3fbc5a2f (diff)
downloadchrome-ec-c56df0d8314358709ef58f2dd82a858d62e30866.tar.gz
ec_chip_mchp: Add other hardware files
Add Micorchip MEC17xx family files for hardware timers, keyboard scan, host port 80h, UART, and watch dog timer. BRANCH=none BUG= TEST=Review only. Change-Id: Iac8a912af4d29521964f606637041b06fa7238ee Signed-off-by: Scott Worley <scott.worley@microchip.corp-partner.google.com>
Diffstat (limited to 'chip/mchp/watchdog.c')
-rw-r--r--chip/mchp/watchdog.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/chip/mchp/watchdog.c b/chip/mchp/watchdog.c
new file mode 100644
index 0000000000..156edfc750
--- /dev/null
+++ b/chip/mchp/watchdog.c
@@ -0,0 +1,127 @@
+/* Copyright 2017 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.
+ */
+
+/* Watchdog driver */
+
+#include "hooks.h"
+#include "registers.h"
+#include "task.h"
+#include "watchdog.h"
+#include "tfdp_chip.h"
+
+void watchdog_reload(void)
+{
+ MCHP_WDG_KICK = 1;
+
+#ifdef CONFIG_WATCHDOG_HELP
+ /* Reload the auxiliary timer */
+ MCHP_TMR16_CTL(0) &= ~(1 << 5);
+ MCHP_TMR16_CNT(0) = CONFIG_AUX_TIMER_PERIOD_MS;
+#ifndef CONFIG_CHIPSET_DEBUG
+ MCHP_TMR16_CTL(0) |= 1 << 5;
+#endif
+#endif
+}
+DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT);
+
+int watchdog_init(void)
+{
+#ifdef CONFIG_WATCHDOG_HELP
+ uint32_t val;
+
+ /*
+ * Watchdog does not warn us before expiring. Let's use a 16-bit
+ * timer as an auxiliary timer.
+ */
+
+ /* Clear 16-bit basic timer 0 PCR sleep enable */
+ MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_BTMR16_0);
+
+ /* Stop the auxiliary timer if it's running */
+ MCHP_TMR16_CTL(0) &= ~(1 << 5);
+
+ /* Enable auxiliary timer */
+ MCHP_TMR16_CTL(0) |= 1 << 0;
+
+ val = MCHP_TMR16_CTL(0);
+
+ /* Pre-scale = 48000 -> 1kHz -> Period = 1ms */
+ val = (val & 0xffff) | (47999 << 16);
+
+ /* No auto restart */
+ val &= ~(1 << 3);
+
+ /* Count down */
+ val &= ~(1 << 2);
+
+ MCHP_TMR16_CTL(0) = val;
+
+#ifndef CONFIG_CHIPSET_DEBUG
+ /* Enable interrupt from auxiliary timer */
+ MCHP_TMR16_IEN(0) |= 1;
+ task_enable_irq(MCHP_IRQ_TIMER16_0);
+ MCHP_INT_ENABLE(MCHP_TMR16_GIRQ) = MCHP_TMR16_GIRQ_BIT(0);
+
+ /* Load and start the auxiliary timer */
+ MCHP_TMR16_CNT(0) = CONFIG_AUX_TIMER_PERIOD_MS;
+ MCHP_TMR16_CNT(0) |= 1 << 5;
+#endif
+#endif
+
+ /* Clear WDT PCR sleep enable */
+ MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_WDT);
+
+ /* Set timeout. It takes 1007us to decrement WDG_CNT by 1. */
+ MCHP_WDG_LOAD = CONFIG_WATCHDOG_PERIOD_MS * 1000 / 1007;
+
+ /* Start watchdog */
+#ifdef CONFIG_CHIPSET_DEBUG
+ /* debug, set stall and do not start */
+ MCHP_WDG_CTL = (1 << 4); /* enable WDG stall on active JTAG */
+#else
+ MCHP_WDG_CTL |= 1;
+#endif
+
+ return EC_SUCCESS;
+}
+
+#ifdef CONFIG_WATCHDOG_HELP
+void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
+{
+ trace0(0, WDT, 0, "Watchdog check from 16-bit basic timer0 ISR");
+
+ /* Clear status */
+ MCHP_TMR16_STS(0) |= 1;
+ /* clear aggregator status */
+ MCHP_INT_SOURCE(MCHP_TMR16_GIRQ) = MCHP_TMR16_GIRQ_BIT(0);
+
+ watchdog_trace(excep_lr, excep_sp);
+}
+
+void
+IRQ_HANDLER(MCHP_IRQ_TIMER16_0)(void) __keep __attribute__((naked));
+void IRQ_HANDLER(MCHP_IRQ_TIMER16_0)(void)
+{
+ /* Naked call so we can extract raw LR and SP */
+ asm volatile("mov r0, lr\n"
+ "mov r1, sp\n"
+ /*
+ * Must push registers in pairs to keep 64-bit aligned
+ * stack for ARM EABI. This also conveninently saves
+ * R0=LR so we can pass it to task_resched_if_needed.
+ */
+ "push {r0, lr}\n"
+ "bl watchdog_check\n"
+ "pop {r0, lr}\n"
+ "b task_resched_if_needed\n");
+}
+
+/*
+ * Put the watchdog at the highest interrupt priority.
+ */
+const struct irq_priority __keep IRQ_PRIORITY(MEC1322_IRQ_TIMER16_0)
+ __attribute__((section(".rodata.irqprio")))
+ = {MCHP_IRQ_TIMER16_0, 0};
+#endif