1
2
3
4
5
6
7
8
9
10
11#include <common.h>
12#include <command.h>
13#include <malloc.h>
14#include <asm/microblaze_intc.h>
15#include <asm/asm.h>
16
17void enable_interrupts(void)
18{
19 debug("Enable interrupts for the whole CPU\n");
20 MSRSET(0x2);
21}
22
23int disable_interrupts(void)
24{
25 unsigned int msr;
26
27 MFS(msr, rmsr);
28 MSRCLR(0x2);
29 return (msr & 0x2) != 0;
30}
31
32static struct irq_action *vecs;
33static u32 irq_no;
34
35
36microblaze_intc_t *intc;
37
38
39static void def_hdlr(void)
40{
41 puts("def_hdlr\n");
42}
43
44static void enable_one_interrupt(int irq)
45{
46 int mask;
47 int offset = 1;
48
49 offset <<= irq;
50 mask = intc->ier;
51 intc->ier = (mask | offset);
52
53 debug("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
54 intc->ier);
55 debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
56 intc->iar, intc->mer);
57}
58
59static void disable_one_interrupt(int irq)
60{
61 int mask;
62 int offset = 1;
63
64 offset <<= irq;
65 mask = intc->ier;
66 intc->ier = (mask & ~offset);
67
68 debug("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
69 intc->ier);
70 debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
71 intc->iar, intc->mer);
72}
73
74int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
75{
76 struct irq_action *act;
77
78
79 if ((irq < 0) || (irq > irq_no)) {
80 puts("IRQ out of range\n");
81 return -1;
82 }
83 act = &vecs[irq];
84 if (hdlr) {
85 act->handler = hdlr;
86 act->arg = arg;
87 act->count = 0;
88 enable_one_interrupt(irq);
89 return 0;
90 }
91
92
93 act->handler = (interrupt_handler_t *)def_hdlr;
94 act->arg = (void *)irq;
95 disable_one_interrupt(irq);
96 return 1;
97}
98
99
100static void intc_init(void)
101{
102 intc->mer = 0;
103 intc->ier = 0;
104 intc->iar = 0xFFFFFFFF;
105
106 intc->mer = 0x3;
107
108 debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
109 intc->iar, intc->mer);
110}
111
112int interrupt_init(void)
113{
114 int i;
115
116#if defined(CONFIG_SYS_INTC_0_ADDR) && defined(CONFIG_SYS_INTC_0_NUM)
117 intc = (microblaze_intc_t *)CONFIG_SYS_INTC_0_ADDR;
118 irq_no = CONFIG_SYS_INTC_0_NUM;
119#endif
120 if (irq_no) {
121 vecs = calloc(1, sizeof(struct irq_action) * irq_no);
122 if (vecs == NULL) {
123 puts("Interrupt vector allocation failed\n");
124 return -1;
125 }
126
127
128 for (i = 0; i < irq_no; i++) {
129 vecs[i].handler = (interrupt_handler_t *)def_hdlr;
130 vecs[i].arg = (void *)i;
131 vecs[i].count = 0;
132 }
133
134 intc_init();
135 enable_interrupts();
136 } else {
137 puts("Undefined interrupt controller\n");
138 }
139 return 0;
140}
141
142void interrupt_handler(void)
143{
144 int irqs = intc->ivr;
145 int mask = 1;
146 int value;
147 struct irq_action *act = vecs + irqs;
148
149 debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
150 intc->iar, intc->mer);
151#ifdef DEBUG
152 R14(value);
153#endif
154 debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
155
156 debug("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
157 (u32)act->handler, act->count, (u32)act->arg);
158 act->handler(act->arg);
159 act->count++;
160
161 intc->iar = mask << irqs;
162
163 debug("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
164 intc->ier, intc->iar, intc->mer);
165#ifdef DEBUG
166 R14(value);
167#endif
168 debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
169}
170
171#if defined(CONFIG_CMD_IRQ)
172int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, const char *argv[])
173{
174 int i;
175 struct irq_action *act = vecs;
176
177 if (irq_no) {
178 puts("\nInterrupt-Information:\n\n"
179 "Nr Routine Arg Count\n"
180 "-----------------------------\n");
181
182 for (i = 0; i < irq_no; i++) {
183 if (act->handler != (interrupt_handler_t *)def_hdlr) {
184 printf("%02d %08x %08x %d\n", i,
185 (int)act->handler, (int)act->arg,
186 act->count);
187 }
188 act++;
189 }
190 puts("\n");
191 } else {
192 puts("Undefined interrupt controller\n");
193 }
194 return 0;
195}
196#endif
197