1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2007 Michal Simek
4 * (C) Copyright 2004 Atmark Techno, Inc.
6 * Michal SIMEK <monstr@monstr.eu>
7 * Yasushi SHOJI <yashi@atmark-techno.com>
16 #include <asm/global_data.h>
17 #include <asm/microblaze_intc.h>
20 DECLARE_GLOBAL_DATA_PTR;
22 void enable_interrupts(void)
24 debug("Enable interrupts for the whole CPU\n");
28 int disable_interrupts(void)
34 return (msr & 0x2) != 0;
37 static struct irq_action *vecs;
40 /* mapping structure to interrupt controller */
41 microblaze_intc_t *intc;
44 static void def_hdlr(void)
49 static void enable_one_interrupt(int irq)
56 intc->ier = (mask | offset);
58 debug("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
60 debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
61 intc->iar, intc->mer);
64 static void disable_one_interrupt(int irq)
71 intc->ier = (mask & ~offset);
73 debug("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
75 debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
76 intc->iar, intc->mer);
79 int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
81 struct irq_action *act;
83 /* irq out of range */
84 if ((irq < 0) || (irq > irq_no)) {
85 puts("IRQ out of range\n");
89 if (hdlr) { /* enable */
93 enable_one_interrupt(irq);
98 act->handler = (interrupt_handler_t *)def_hdlr;
99 act->arg = (void *)irq;
100 disable_one_interrupt(irq);
104 /* initialization interrupt controller - hardware */
105 static void intc_init(void)
109 intc->iar = 0xFFFFFFFF;
110 /* XIntc_Start - hw_interrupt enable and all interrupt enable */
113 debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
114 intc->iar, intc->mer);
117 int interrupt_init(void)
120 const void *blob = gd->fdt_blob;
123 debug("INTC: Initialization\n");
125 node = fdt_node_offset_by_compatible(blob, node,
126 "xlnx,xps-intc-1.00.a");
128 fdt_addr_t base = fdtdec_get_addr(blob, node, "reg");
129 if (base == FDT_ADDR_T_NONE)
132 debug("INTC: Base addr %lx\n", base);
133 intc = (microblaze_intc_t *)base;
134 irq_no = fdtdec_get_int(blob, node, "xlnx,num-intr-inputs", 0);
135 debug("INTC: IRQ NO %x\n", irq_no);
141 vecs = calloc(1, sizeof(struct irq_action) * irq_no);
143 puts("Interrupt vector allocation failed\n");
147 /* initialize irq list */
148 for (i = 0; i < irq_no; i++) {
149 vecs[i].handler = (interrupt_handler_t *)def_hdlr;
150 vecs[i].arg = (void *)i;
153 /* initialize intc controller */
157 puts("Undefined interrupt controller\n");
162 void interrupt_handler(void)
164 int irqs = intc->ivr; /* find active interrupt */
167 struct irq_action *act = vecs + irqs;
169 debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
170 intc->iar, intc->mer);
174 debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
176 debug("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
177 (u32)act->handler, act->count, (u32)act->arg);
178 act->handler(act->arg);
181 intc->iar = mask << irqs;
183 debug("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
184 intc->ier, intc->iar, intc->mer);
188 debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
191 #if defined(CONFIG_CMD_IRQ)
192 int do_irqinfo(struct cmd_tbl *cmdtp, int flag, int argc, const char *argv[])
195 struct irq_action *act = vecs;
198 puts("\nInterrupt-Information:\n\n"
199 "Nr Routine Arg Count\n"
200 "-----------------------------\n");
202 for (i = 0; i < irq_no; i++) {
203 if (act->handler != (interrupt_handler_t *)def_hdlr) {
204 printf("%02d %08x %08x %d\n", i,
205 (int)act->handler, (int)act->arg,
212 puts("Undefined interrupt controller\n");