command: Remove the cmd_tbl_t typedef
[oweals/u-boot.git] / arch / microblaze / cpu / interrupts.c
index a6021c99c3b2ab6a563fdfb1acc14b2ce6ed3d30..a6a52f85270a851f5de3f716aafd75bcb3cbad3f 100644 (file)
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2007 Michal Simek
  * (C) Copyright 2004 Atmark Techno, Inc.
  *
  * Michal  SIMEK <monstr@monstr.eu>
  * Yasushi SHOJI <yashi@atmark-techno.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
  */
 
 #include <common.h>
 #include <command.h>
+#include <fdtdec.h>
+#include <irq_func.h>
+#include <malloc.h>
 #include <asm/microblaze_intc.h>
 #include <asm/asm.h>
 
-#undef DEBUG_INT
-
-extern void microblaze_disable_interrupts (void);
-extern void microblaze_enable_interrupts (void);
+DECLARE_GLOBAL_DATA_PTR;
 
-void enable_interrupts (void)
+void enable_interrupts(void)
 {
+       debug("Enable interrupts for the whole CPU\n");
        MSRSET(0x2);
 }
 
-int disable_interrupts (void)
+int disable_interrupts(void)
 {
+       unsigned int msr;
+
+       MFS(msr, rmsr);
        MSRCLR(0x2);
-       return 0;
+       return (msr & 0x2) != 0;
 }
 
-#ifdef CONFIG_SYS_INTC_0
-#ifdef CONFIG_SYS_TIMER_0
-extern void timer_init (void);
-#endif
-#ifdef CONFIG_SYS_FSL_2
-extern void fsl_init2 (void);
-#endif
-
-
-static struct irq_action vecs[CONFIG_SYS_INTC_0_NUM];
+static struct irq_action *vecs;
+static u32 irq_no;
 
 /* mapping structure to interrupt controller */
-microblaze_intc_t *intc = (microblaze_intc_t *) (CONFIG_SYS_INTC_0_ADDR);
+microblaze_intc_t *intc;
 
 /* default handler */
-void def_hdlr (void)
+static void def_hdlr(void)
 {
-       puts ("def_hdlr\n");
+       puts("def_hdlr\n");
 }
 
-void enable_one_interrupt (int irq)
+static void enable_one_interrupt(int irq)
 {
        int mask;
        int offset = 1;
+
        offset <<= irq;
        mask = intc->ier;
        intc->ier = (mask | offset);
-#ifdef DEBUG_INT
-       printf ("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
-               intc->ier);
-       printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-               intc->iar, intc->mer);
-#endif
+
+       debug("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
+             intc->ier);
+       debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+             intc->iar, intc->mer);
 }
 
-void disable_one_interrupt (int irq)
+static void disable_one_interrupt(int irq)
 {
        int mask;
        int offset = 1;
+
        offset <<= irq;
        mask = intc->ier;
        intc->ier = (mask & ~offset);
-#ifdef DEBUG_INT
-       printf ("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
-               intc->ier);
-       printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-               intc->iar, intc->mer);
-#endif
+
+       debug("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
+             intc->ier);
+       debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+             intc->iar, intc->mer);
 }
 
-/* adding new handler for interrupt */
-void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg)
+int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
 {
        struct irq_action *act;
+
        /* irq out of range */
-       if ((irq < 0) || (irq > CONFIG_SYS_INTC_0_NUM)) {
-               puts ("IRQ out of range\n");
-               return;
+       if ((irq < 0) || (irq > irq_no)) {
+               puts("IRQ out of range\n");
+               return -1;
        }
        act = &vecs[irq];
        if (hdlr) {             /* enable */
                act->handler = hdlr;
                act->arg = arg;
                act->count = 0;
-               enable_one_interrupt (irq);
-       } else {                /* disable */
-               act->handler = (interrupt_handler_t *) def_hdlr;
-               act->arg = (void *)irq;
-               disable_one_interrupt (irq);
+               enable_one_interrupt(irq);
+               return 0;
        }
+
+       /* Disable */
+       act->handler = (interrupt_handler_t *)def_hdlr;
+       act->arg = (void *)irq;
+       disable_one_interrupt(irq);
+       return 1;
 }
 
 /* initialization interrupt controller - hardware */
-void intc_init (void)
+static void intc_init(void)
 {
        intc->mer = 0;
        intc->ier = 0;
        intc->iar = 0xFFFFFFFF;
        /* XIntc_Start - hw_interrupt enable and all interrupt enable */
        intc->mer = 0x3;
-#ifdef DEBUG_INT
-       printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-               intc->iar, intc->mer);
-#endif
+
+       debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+             intc->iar, intc->mer);
 }
 
-int interrupts_init (void)
+int interrupt_init(void)
 {
        int i;
-       /* initialize irq list */
-       for (i = 0; i < CONFIG_SYS_INTC_0_NUM; i++) {
-               vecs[i].handler = (interrupt_handler_t *) def_hdlr;
-               vecs[i].arg = (void *)i;
-               vecs[i].count = 0;
+       const void *blob = gd->fdt_blob;
+       int node = 0;
+
+       debug("INTC: Initialization\n");
+
+       node = fdt_node_offset_by_compatible(blob, node,
+                               "xlnx,xps-intc-1.00.a");
+       if (node != -1) {
+               fdt_addr_t base = fdtdec_get_addr(blob, node, "reg");
+               if (base == FDT_ADDR_T_NONE)
+                       return -1;
+
+               debug("INTC: Base addr %lx\n", base);
+               intc = (microblaze_intc_t *)base;
+               irq_no = fdtdec_get_int(blob, node, "xlnx,num-intr-inputs", 0);
+               debug("INTC: IRQ NO %x\n", irq_no);
+       } else {
+               return node;
+       }
+
+       if (irq_no) {
+               vecs = calloc(1, sizeof(struct irq_action) * irq_no);
+               if (vecs == NULL) {
+                       puts("Interrupt vector allocation failed\n");
+                       return -1;
+               }
+
+               /* initialize irq list */
+               for (i = 0; i < irq_no; i++) {
+                       vecs[i].handler = (interrupt_handler_t *)def_hdlr;
+                       vecs[i].arg = (void *)i;
+                       vecs[i].count = 0;
+               }
+               /* initialize intc controller */
+               intc_init();
+               enable_interrupts();
+       } else {
+               puts("Undefined interrupt controller\n");
        }
-       /* initialize intc controller */
-       intc_init ();
-#ifdef CONFIG_SYS_TIMER_0
-       timer_init ();
-#endif
-#ifdef CONFIG_SYS_FSL_2
-       fsl_init2 ();
-#endif
-       enable_interrupts ();
        return 0;
 }
 
-void interrupt_handler (void)
+void interrupt_handler(void)
 {
-       int irqs = (intc->isr & intc->ier);     /* find active interrupt */
-       int i = 1;
-#ifdef DEBUG_INT
+       int irqs = intc->ivr;   /* find active interrupt */
+       int mask = 1;
        int value;
-       printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-               intc->iar, intc->mer);
+       struct irq_action *act = vecs + irqs;
+
+       debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+             intc->iar, intc->mer);
+#ifdef DEBUG
        R14(value);
-       printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
-#endif
-       struct irq_action *act = vecs;
-       while (irqs) {
-               if (irqs & 1) {
-#ifdef DEBUG_INT
-                       printf
-                           ("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
-                            act->handler, act->count, act->arg);
 #endif
-                       act->handler (act->arg);
-                       act->count++;
-                       intc->iar = i;
-                       return;
-               }
-               irqs >>= 1;
-               act++;
-               i <<= 1;
-       }
+       debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
+
+       debug("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
+             (u32)act->handler, act->count, (u32)act->arg);
+       act->handler(act->arg);
+       act->count++;
 
-#ifdef DEBUG_INT
-       printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
-               intc->ier, intc->iar, intc->mer);
+       intc->iar = mask << irqs;
+
+       debug("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
+             intc->ier, intc->iar, intc->mer);
+#ifdef DEBUG
        R14(value);
-       printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
 #endif
+       debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
 }
-#endif
 
 #if defined(CONFIG_CMD_IRQ)
-#ifdef CONFIG_SYS_INTC_0
-int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+int do_irqinfo(struct cmd_tbl *cmdtp, int flag, int argc, const char *argv[])
 {
        int i;
        struct irq_action *act = vecs;
 
-       puts ("\nInterrupt-Information:\n\n"
-             "Nr  Routine   Arg       Count\n"
-             "-----------------------------\n");
-
-       for (i = 0; i < CONFIG_SYS_INTC_0_NUM; i++) {
-               if (act->handler != (interrupt_handler_t*) def_hdlr) {
-                       printf ("%02d  %08x  %08x  %d\n", i,
-                               (int)act->handler, (int)act->arg, act->count);
+       if (irq_no) {
+               puts("\nInterrupt-Information:\n\n"
+                     "Nr  Routine   Arg       Count\n"
+                     "-----------------------------\n");
+
+               for (i = 0; i < irq_no; i++) {
+                       if (act->handler != (interrupt_handler_t *)def_hdlr) {
+                               printf("%02d  %08x  %08x  %d\n", i,
+                                      (int)act->handler, (int)act->arg,
+                                      act->count);
+                       }
+                       act++;
                }
-               act++;
+               puts("\n");
+       } else {
+               puts("Undefined interrupt controller\n");
        }
-       puts ("\n");
-       return (0);
-}
-#else
-int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
-{
-       puts ("Undefined interrupt controller\n");
+       return 0;
 }
 #endif
-#endif