1 /*
2 * Copyright (c) 2015 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8 #include <lk/reg.h>
9 #include <lk/err.h>
10 #include <lk/trace.h>
11 #include <lk/init.h>
12 #include <kernel/thread.h>
13 #include <platform.h>
14 #include <platform/interrupts.h>
15 #include <platform/debug.h>
16 #include <sys/types.h>
17 #include <target/microblaze-config.h>
18
19 #define LOCAL_TRACE 0
20
21 #define R_ISR 0
22 #define R_IPR 1
23 #define R_IER 2
24 #define R_IAR 3
25 #define R_SIE 4
26 #define R_CIE 5
27 #define R_IVR 6
28 #define R_MER 7
29 #define R_MAX 8
30
31 #define INTC_REG(reg) (*REG32(INTC_BASEADDR + (reg) * 4))
32
33 static spin_lock_t lock;
34
35 struct int_handler_struct {
36 int_handler handler;
37 void *arg;
38 };
39
40 static struct int_handler_struct int_handler_table[MAX_INT];
41
register_int_handler(unsigned int vector,int_handler handler,void * arg)42 void register_int_handler(unsigned int vector, int_handler handler, void *arg) {
43 LTRACEF("vector %u, handler %p, arg %p\n", vector, handler, arg);
44
45 if (vector >= MAX_INT)
46 return;
47
48 spin_lock_saved_state_t state;
49 spin_lock_irqsave(&lock, state);
50
51 int_handler_table[vector].handler = handler;
52 int_handler_table[vector].arg = arg;
53
54 spin_unlock_irqrestore(&lock, state);
55 }
56
mask_interrupt(unsigned int vector)57 status_t mask_interrupt(unsigned int vector) {
58 LTRACEF("vector %u\n", vector);
59
60 INTC_REG(R_CIE) = 1 << vector;
61
62 return NO_ERROR;
63 }
64
unmask_interrupt(unsigned int vector)65 status_t unmask_interrupt(unsigned int vector) {
66 LTRACEF("vector %u\n", vector);
67
68 INTC_REG(R_SIE) = 1 << vector;
69
70 return NO_ERROR;
71 }
72
73 enum handler_return platform_irq_handler(void);
platform_irq_handler(void)74 enum handler_return platform_irq_handler(void) {
75 enum handler_return ret = INT_NO_RESCHEDULE;
76
77 uint irq = INTC_REG(R_IVR);
78 LTRACEF("irq %u, IPR 0x%x, ISR 0x%x\n", irq, INTC_REG(R_IPR), INTC_REG(R_ISR));
79
80 if (irq < MAX_INT && int_handler_table[irq].handler)
81 ret = int_handler_table[irq].handler(int_handler_table[irq].arg);
82
83 INTC_REG(R_IAR) = 1 << irq;
84
85 return ret;
86 }
87
intc_init(uint level)88 static void intc_init(uint level) {
89 LTRACE;
90
91 INTC_REG(R_CIE) = 0xffffffff;
92 INTC_REG(R_MER) = 0x3;
93 }
94
95 LK_INIT_HOOK(intc, intc_init, LK_INIT_LEVEL_PLATFORM_EARLY);
96
97