]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/microblaze/cpu/interrupts.c
karo: fdt: fix panel-dpi support
[karo-tx-uboot.git] / arch / microblaze / cpu / interrupts.c
1 /*
2  * (C) Copyright 2007 Michal Simek
3  * (C) Copyright 2004 Atmark Techno, Inc.
4  *
5  * Michal  SIMEK <monstr@monstr.eu>
6  * Yasushi SHOJI <yashi@atmark-techno.com>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
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
17 void enable_interrupts(void)
18 {
19         debug("Enable interrupts for the whole CPU\n");
20         MSRSET(0x2);
21 }
22
23 int disable_interrupts(void)
24 {
25         unsigned int msr;
26
27         MFS(msr, rmsr);
28         MSRCLR(0x2);
29         return (msr & 0x2) != 0;
30 }
31
32 static struct irq_action *vecs;
33 static u32 irq_no;
34
35 /* mapping structure to interrupt controller */
36 microblaze_intc_t *intc;
37
38 /* default handler */
39 static void def_hdlr(void)
40 {
41         puts("def_hdlr\n");
42 }
43
44 static 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
59 static 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
74 int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
75 {
76         struct irq_action *act;
77
78         /* irq out of range */
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) {             /* enable */
85                 act->handler = hdlr;
86                 act->arg = arg;
87                 act->count = 0;
88                 enable_one_interrupt(irq);
89                 return 0;
90         }
91
92         /* Disable */
93         act->handler = (interrupt_handler_t *)def_hdlr;
94         act->arg = (void *)irq;
95         disable_one_interrupt(irq);
96         return 1;
97 }
98
99 /* initialization interrupt controller - hardware */
100 static void intc_init(void)
101 {
102         intc->mer = 0;
103         intc->ier = 0;
104         intc->iar = 0xFFFFFFFF;
105         /* XIntc_Start - hw_interrupt enable and all interrupt enable */
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
112 int 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                 /* initialize irq list */
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                 /* initialize intc controller */
134                 intc_init();
135                 enable_interrupts();
136         } else {
137                 puts("Undefined interrupt controller\n");
138         }
139         return 0;
140 }
141
142 void interrupt_handler(void)
143 {
144         int irqs = intc->ivr;   /* find active interrupt */
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)
172 int 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