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