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