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_FSL_2 50 extern void fsl_init2 (void); 51 #endif 52 53 54 static struct irq_action vecs[CONFIG_SYS_INTC_0_NUM]; 55 56 /* mapping structure to interrupt controller */ 57 microblaze_intc_t *intc = (microblaze_intc_t *) (CONFIG_SYS_INTC_0_ADDR); 58 59 /* default handler */ 60 void def_hdlr (void) 61 { 62 puts ("def_hdlr\n"); 63 } 64 65 void enable_one_interrupt (int irq) 66 { 67 int mask; 68 int offset = 1; 69 offset <<= irq; 70 mask = intc->ier; 71 intc->ier = (mask | offset); 72 #ifdef DEBUG_INT 73 printf ("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask, 74 intc->ier); 75 printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, 76 intc->iar, intc->mer); 77 #endif 78 } 79 80 void disable_one_interrupt (int irq) 81 { 82 int mask; 83 int offset = 1; 84 offset <<= irq; 85 mask = intc->ier; 86 intc->ier = (mask & ~offset); 87 #ifdef DEBUG_INT 88 printf ("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask, 89 intc->ier); 90 printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, 91 intc->iar, intc->mer); 92 #endif 93 } 94 95 /* adding new handler for interrupt */ 96 void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg) 97 { 98 struct irq_action *act; 99 /* irq out of range */ 100 if ((irq < 0) || (irq > CONFIG_SYS_INTC_0_NUM)) { 101 puts ("IRQ out of range\n"); 102 return; 103 } 104 act = &vecs[irq]; 105 if (hdlr) { /* enable */ 106 act->handler = hdlr; 107 act->arg = arg; 108 act->count = 0; 109 enable_one_interrupt (irq); 110 } else { /* disable */ 111 act->handler = (interrupt_handler_t *) def_hdlr; 112 act->arg = (void *)irq; 113 disable_one_interrupt (irq); 114 } 115 } 116 117 /* initialization interrupt controller - hardware */ 118 void intc_init (void) 119 { 120 intc->mer = 0; 121 intc->ier = 0; 122 intc->iar = 0xFFFFFFFF; 123 /* XIntc_Start - hw_interrupt enable and all interrupt enable */ 124 intc->mer = 0x3; 125 #ifdef DEBUG_INT 126 printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, 127 intc->iar, intc->mer); 128 #endif 129 } 130 131 int interrupts_init (void) 132 { 133 int i; 134 /* initialize irq list */ 135 for (i = 0; i < CONFIG_SYS_INTC_0_NUM; i++) { 136 vecs[i].handler = (interrupt_handler_t *) def_hdlr; 137 vecs[i].arg = (void *)i; 138 vecs[i].count = 0; 139 } 140 /* initialize intc controller */ 141 intc_init (); 142 #ifdef CONFIG_SYS_FSL_2 143 fsl_init2 (); 144 #endif 145 enable_interrupts (); 146 return 0; 147 } 148 149 void interrupt_handler (void) 150 { 151 int irqs = (intc->isr & intc->ier); /* find active interrupt */ 152 int i = 1; 153 #ifdef DEBUG_INT 154 int value; 155 printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, 156 intc->iar, intc->mer); 157 R14(value); 158 printf ("Interrupt handler on %x line, r14 %x\n", irqs, value); 159 #endif 160 struct irq_action *act = vecs; 161 while (irqs) { 162 if (irqs & 1) { 163 #ifdef DEBUG_INT 164 printf 165 ("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n", 166 act->handler, act->count, act->arg); 167 #endif 168 act->handler (act->arg); 169 act->count++; 170 intc->iar = i; 171 return; 172 } 173 irqs >>= 1; 174 act++; 175 i <<= 1; 176 } 177 178 #ifdef DEBUG_INT 179 printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr, 180 intc->ier, intc->iar, intc->mer); 181 R14(value); 182 printf ("Interrupt handler on %x line, r14 %x\n", irqs, value); 183 #endif 184 } 185 #endif 186 187 #if defined(CONFIG_CMD_IRQ) 188 #ifdef CONFIG_SYS_INTC_0 189 int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 190 { 191 int i; 192 struct irq_action *act = vecs; 193 194 puts ("\nInterrupt-Information:\n\n" 195 "Nr Routine Arg Count\n" 196 "-----------------------------\n"); 197 198 for (i = 0; i < CONFIG_SYS_INTC_0_NUM; i++) { 199 if (act->handler != (interrupt_handler_t*) def_hdlr) { 200 printf ("%02d %08x %08x %d\n", i, 201 (int)act->handler, (int)act->arg, act->count); 202 } 203 act++; 204 } 205 puts ("\n"); 206 return (0); 207 } 208 #else 209 int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 210 { 211 puts ("Undefined interrupt controller\n"); 212 } 213 #endif 214 #endif 215