uboot/arch/powerpc/cpu/ppc4xx/interrupts.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2002
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * (C) Copyright 2002 (440 port)
   6 * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
   7 *
   8 * (C) Copyright 2003 (440GX port)
   9 * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
  10 *
  11 * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
  12 * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@gmail.com
  13 * Work supported by Qtechnology (htpp://qtec.com)
  14 *
  15 * SPDX-License-Identifier:     GPL-2.0+
  16 */
  17
  18#include <common.h>
  19#include <watchdog.h>
  20#include <command.h>
  21#include <asm/processor.h>
  22#include <asm/interrupt.h>
  23#include <asm/ppc4xx.h>
  24#include <ppc_asm.tmpl>
  25#include <commproc.h>
  26
  27DECLARE_GLOBAL_DATA_PTR;
  28
  29/*
  30 * CPM interrupt vector functions.
  31 */
  32struct  irq_action {
  33        interrupt_handler_t *handler;
  34        void *arg;
  35        int count;
  36};
  37static struct irq_action irq_vecs[IRQ_MAX];
  38
  39#if defined(CONFIG_440)
  40
  41/* SPRN changed in 440 */
  42static __inline__ void set_evpr(unsigned long val)
  43{
  44        asm volatile("mtspr 0x03f,%0" : : "r" (val));
  45}
  46
  47#else /* !defined(CONFIG_440) */
  48
  49static __inline__ void set_pit(unsigned long val)
  50{
  51        asm volatile("mtpit %0" : : "r" (val));
  52}
  53
  54static __inline__ void set_evpr(unsigned long val)
  55{
  56        asm volatile("mtevpr %0" : : "r" (val));
  57}
  58#endif /* defined(CONFIG_440 */
  59
  60int interrupt_init_cpu (unsigned *decrementer_count)
  61{
  62        int vec;
  63        unsigned long val;
  64
  65        /* decrementer is automatically reloaded */
  66        *decrementer_count = 0;
  67
  68        /*
  69         * Mark all irqs as free
  70         */
  71        for (vec = 0; vec < IRQ_MAX; vec++) {
  72                irq_vecs[vec].handler = NULL;
  73                irq_vecs[vec].arg = NULL;
  74                irq_vecs[vec].count = 0;
  75        }
  76
  77#ifdef CONFIG_4xx
  78        /*
  79         * Init PIT
  80         */
  81#if defined(CONFIG_440)
  82        val = mfspr( SPRN_TCR );
  83        val &= (~0x04400000);           /* clear DIS & ARE */
  84        mtspr( SPRN_TCR, val );
  85        mtspr( SPRN_DEC, 0 );           /* Prevent exception after TSR clear*/
  86        mtspr( SPRN_DECAR, 0 );         /* clear reload */
  87        mtspr( SPRN_TSR, 0x08000000 );  /* clear DEC status */
  88        val = gd->bd->bi_intfreq/1000;  /* 1 msec */
  89        mtspr( SPRN_DECAR, val );               /* Set auto-reload value */
  90        mtspr( SPRN_DEC, val );         /* Set inital val */
  91#else
  92        set_pit(gd->bd->bi_intfreq / 1000);
  93#endif
  94#endif  /* CONFIG_4xx */
  95
  96#ifdef CONFIG_ADCIOP
  97        /*
  98         * Init PIT
  99         */
 100        set_pit(66000);
 101#endif
 102
 103        /*
 104         * Enable PIT
 105         */
 106        val = mfspr(SPRN_TCR);
 107        val |= 0x04400000;
 108        mtspr(SPRN_TCR, val);
 109
 110        /*
 111         * Set EVPR to 0
 112         */
 113        set_evpr(0x00000000);
 114
 115        /*
 116         * Call uic or xilinx_irq pic_enable
 117         */
 118        pic_enable();
 119
 120        return (0);
 121}
 122
 123void timer_interrupt_cpu(struct pt_regs *regs)
 124{
 125        /* nothing to do here */
 126        return;
 127}
 128
 129void interrupt_run_handler(int vec)
 130{
 131        irq_vecs[vec].count++;
 132
 133        if (irq_vecs[vec].handler != NULL) {
 134                /* call isr */
 135                (*irq_vecs[vec].handler) (irq_vecs[vec].arg);
 136        } else {
 137                pic_irq_disable(vec);
 138                printf("Masking bogus interrupt vector %d\n", vec);
 139        }
 140
 141        pic_irq_ack(vec);
 142        return;
 143}
 144
 145void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
 146{
 147        /*
 148         * Print warning when replacing with a different irq vector
 149         */
 150        if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
 151                printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
 152                       vec, (uint) handler, (uint) irq_vecs[vec].handler);
 153        }
 154        irq_vecs[vec].handler = handler;
 155        irq_vecs[vec].arg = arg;
 156
 157        pic_irq_enable(vec);
 158        return;
 159}
 160
 161void irq_free_handler(int vec)
 162{
 163        debug("Free interrupt for vector %d ==> %p\n",
 164              vec, irq_vecs[vec].handler);
 165
 166        pic_irq_disable(vec);
 167
 168        irq_vecs[vec].handler = NULL;
 169        irq_vecs[vec].arg = NULL;
 170        return;
 171}
 172
 173#if defined(CONFIG_CMD_IRQ)
 174int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 175{
 176        int vec;
 177
 178        printf ("Interrupt-Information:\n");
 179        printf ("Nr  Routine   Arg       Count\n");
 180
 181        for (vec = 0; vec < IRQ_MAX; vec++) {
 182                if (irq_vecs[vec].handler != NULL) {
 183                        printf ("%02d  %08lx  %08lx  %d\n",
 184                                vec,
 185                                (ulong)irq_vecs[vec].handler,
 186                                (ulong)irq_vecs[vec].arg,
 187                                irq_vecs[vec].count);
 188                }
 189        }
 190
 191        return 0;
 192}
 193#endif
 194