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 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 */ 26 27 #include <common.h> 28 #include <command.h> 29 #include <asm/microblaze_intc.h> 30 #include <asm/asm.h> 31 32 #undef DEBUG_INT 33 34 extern void microblaze_disable_interrupts (void); 35 extern void microblaze_enable_interrupts (void); 36 37 void enable_interrupts (void) 38 { 39 MSRSET(0x2); 40 } 41 42 int disable_interrupts (void) 43 { 44 MSRCLR(0x2); 45 return 0; 46 } 47 48 #ifdef CONFIG_SYS_INTC_0 49 #ifdef CONFIG_SYS_TIMER_0 50 extern void timer_init (void); 51 #endif 52 #ifdef CONFIG_SYS_FSL_2 53 extern void fsl_init2 (void); 54 #endif 55 56 57 static struct irq_action vecs[CONFIG_SYS_INTC_0_NUM]; 58 59 /* mapping structure to interrupt controller */ 60 microblaze_intc_t *intc = (microblaze_intc_t *) (CONFIG_SYS_INTC_0_ADDR); 61 62 /* default handler */ 63 void def_hdlr (void) 64 { 65 puts ("def_hdlr\n"); 66 } 67 68 void enable_one_interrupt (int irq) 69 { 70 int mask; 71 int offset = 1; 72 offset <<= irq; 73 mask = intc->ier; 74 intc->ier = (mask | offset); 75 #ifdef DEBUG_INT 76 printf ("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask, 77 intc->ier); 78 printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, 79 intc->iar, intc->mer); 80 #endif 81 } 82 83 void disable_one_interrupt (int irq) 84 { 85 int mask; 86 int offset = 1; 87 offset <<= irq; 88 mask = intc->ier; 89 intc->ier = (mask & ~offset); 90 #ifdef DEBUG_INT 91 printf ("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask, 92 intc->ier); 93 printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, 94 intc->iar, intc->mer); 95 #endif 96 } 97 98 /* adding new handler for interrupt */ 99 void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg) 100 { 101 struct irq_action *act; 102 /* irq out of range */ 103 if ((irq < 0) || (irq > CONFIG_SYS_INTC_0_NUM)) { 104 puts ("IRQ out of range\n"); 105 return; 106 } 107 act = &vecs[irq]; 108 if (hdlr) { /* enable */ 109 act->handler = hdlr; 110 act->arg = arg; 111 act->count = 0; 112 enable_one_interrupt (irq); 113 } else { /* disable */ 114 act->handler = (interrupt_handler_t *) def_hdlr; 115 act->arg = (void *)irq; 116 disable_one_interrupt (irq); 117 } 118 } 119 120 /* initialization interrupt controller - hardware */ 121 void intc_init (void) 122 { 123 intc->mer = 0; 124 intc->ier = 0; 125 intc->iar = 0xFFFFFFFF; 126 /* XIntc_Start - hw_interrupt enable and all interrupt enable */ 127 intc->mer = 0x3; 128 #ifdef DEBUG_INT 129 printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, 130 intc->iar, intc->mer); 131 #endif 132 } 133 134 int interrupts_init (void) 135 { 136 int i; 137 /* initialize irq list */ 138 for (i = 0; i < CONFIG_SYS_INTC_0_NUM; i++) { 139 vecs[i].handler = (interrupt_handler_t *) def_hdlr; 140 vecs[i].arg = (void *)i; 141 vecs[i].count = 0; 142 } 143 /* initialize intc controller */ 144 intc_init (); 145 #ifdef CONFIG_SYS_TIMER_0 146 timer_init (); 147 #endif 148 #ifdef CONFIG_SYS_FSL_2 149 fsl_init2 (); 150 #endif 151 enable_interrupts (); 152 return 0; 153 } 154 155 void interrupt_handler (void) 156 { 157 int irqs = (intc->isr & intc->ier); /* find active interrupt */ 158 int i = 1; 159 #ifdef DEBUG_INT 160 int value; 161 printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, 162 intc->iar, intc->mer); 163 R14(value); 164 printf ("Interrupt handler on %x line, r14 %x\n", irqs, value); 165 #endif 166 struct irq_action *act = vecs; 167 while (irqs) { 168 if (irqs & 1) { 169 #ifdef DEBUG_INT 170 printf 171 ("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n", 172 act->handler, act->count, act->arg); 173 #endif 174 act->handler (act->arg); 175 act->count++; 176 intc->iar = i; 177 return; 178 } 179 irqs >>= 1; 180 act++; 181 i <<= 1; 182 } 183 184 #ifdef DEBUG_INT 185 printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr, 186 intc->ier, intc->iar, intc->mer); 187 R14(value); 188 printf ("Interrupt handler on %x line, r14 %x\n", irqs, value); 189 #endif 190 } 191 #endif 192 193 #if defined(CONFIG_CMD_IRQ) 194 #ifdef CONFIG_SYS_INTC_0 195 int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 196 { 197 int i; 198 struct irq_action *act = vecs; 199 200 puts ("\nInterrupt-Information:\n\n" 201 "Nr Routine Arg Count\n" 202 "-----------------------------\n"); 203 204 for (i = 0; i < CONFIG_SYS_INTC_0_NUM; i++) { 205 if (act->handler != (interrupt_handler_t*) def_hdlr) { 206 printf ("%02d %08x %08x %d\n", i, 207 (int)act->handler, (int)act->arg, act->count); 208 } 209 act++; 210 } 211 puts ("\n"); 212 return (0); 213 } 214 #else 215 int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 216 { 217 puts ("Undefined interrupt controller\n"); 218 } 219 #endif 220 #endif 221