summaryrefslogtreecommitdiff
path: root/core/minute-ia/irq_handler.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/minute-ia/irq_handler.h')
-rw-r--r--core/minute-ia/irq_handler.h62
1 files changed, 62 insertions, 0 deletions
diff --git a/core/minute-ia/irq_handler.h b/core/minute-ia/irq_handler.h
new file mode 100644
index 0000000000..db05601d6b
--- /dev/null
+++ b/core/minute-ia/irq_handler.h
@@ -0,0 +1,62 @@
+/* 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.
+ */
+
+/* Helper to declare IRQ handling routines */
+
+#ifndef __CROS_EC_IRQ_HANDLER_H
+#define __CROS_EC_IRQ_HANDLER_H
+
+#include "registers.h"
+
+struct irq_data {
+ void (*routine)(void);
+ int irq;
+};
+
+/* Helper macros to build the IRQ handler and priority struct names */
+#define IRQ_HANDLER(irqname) CONCAT3(_irq_, irqname, _handler)
+#define IRQ_PRIORITY(irqname) CONCAT2(prio_, irqname)
+/*
+ * Macro to connect the interrupt handler "routine" to the irq number "irq" and
+ * ensure it is enabled in the interrupt controller with the right priority.
+ *
+ * Note: No 'naked' function support for x86, so function is implemented within
+ * __asm__
+ */
+#define DECLARE_IRQ(irq, routine) DECLARE_IRQ_(irq, routine, irq + 32 + 10)
+/* Each irq has a irq_data structure placed in .rodata.irqs section,
+ * to be used for dynamically setting up interrupt gates */
+#define DECLARE_IRQ_(irq, routine, vector) \
+ void __keep routine(void); \
+ void IRQ_HANDLER(irq)(void); \
+ __asm__ (".section .rodata.irqs\n"); \
+ const struct irq_data __keep CONCAT4(__irq_, irq, _, routine) \
+ __attribute__((section(".rodata.irqs")))= {IRQ_HANDLER(irq), irq};\
+ __asm__ ( \
+ ".section .text._irq_"#irq"_handler\n" \
+ "_irq_"#irq"_handler:\n" \
+ "pusha\n" \
+ "add $1, __in_isr\n" \
+ "call "#routine"\n" \
+ "push $0\n" \
+ "push $0\n" \
+ "call switch_handler\n" \
+ "addl $0x08, %esp\n" \
+ "test %eax, %eax\n" \
+ "je 1f\n" \
+ "movl current_task, %eax\n" \
+ "movl %esp, (%eax)\n" \
+ "movl next_task, %eax\n" \
+ "movl %eax, current_task\n" \
+ "movl (%eax), %esp\n" \
+ "1:\n" \
+ "movl $"#vector ", (0xFEC00040)\n" \
+ "sub $1, __in_isr\n" \
+ "movl $0x00, (0xFEE000B0)\n" \
+ "popa\n" \
+ "iret\n" \
+ );
+
+#endif /* __CROS_EC_IRQ_HANDLER_H */