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@uam.es
  13 * Work supported by Qtechnology (htpp://qtec.com)
  14 *
  15 * See file CREDITS for list of people who contributed to this
  16 * project.
  17 *
  18 * This program is free software; you can redistribute it and/or
  19 * modify it under the terms of the GNU General Public License as
  20 * published by the Free Software Foundation; either version 2 of
  21 * the License, or (at your option) any later version.
  22 *
  23 * This program is distributed in the hope that it will be useful,
  24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26 * GNU General Public License for more details.
  27 *
  28 * You should have received a copy of the GNU General Public License
  29 * along with this program; if not, write to the Free Software
  30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  31 * MA 02111-1307 USA
  32 */
  33
  34#include <common.h>
  35#include <watchdog.h>
  36#include <command.h>
  37#include <asm/processor.h>
  38#include <asm/interrupt.h>
  39#include <asm/ppc4xx.h>
  40#include <ppc_asm.tmpl>
  41#include <commproc.h>
  42
  43DECLARE_GLOBAL_DATA_PTR;
  44
  45/*
  46 * CPM interrupt vector functions.
  47 */
  48struct  irq_action {
  49        interrupt_handler_t *handler;
  50        void *arg;
  51        int count;
  52};
  53static struct irq_action irq_vecs[IRQ_MAX];
  54
  55#if defined(CONFIG_440)
  56
  57/* SPRN changed in 440 */
  58static __inline__ void set_evpr(unsigned long val)
  59{
  60        asm volatile("mtspr 0x03f,%0" : : "r" (val));
  61}
  62
  63#else /* !defined(CONFIG_440) */
  64
  65static __inline__ void set_pit(unsigned long val)
  66{
  67        asm volatile("mtpit %0" : : "r" (val));
  68}
  69
  70static __inline__ void set_evpr(unsigned long val)
  71{
  72        asm volatile("mtevpr %0" : : "r" (val));
  73}
  74#endif /* defined(CONFIG_440 */
  75
  76int interrupt_init_cpu (unsigned *decrementer_count)
  77{
  78        int vec;
  79        unsigned long val;
  80
  81        /* decrementer is automatically reloaded */
  82        *decrementer_count = 0;
  83
  84        /*
  85         * Mark all irqs as free
  86         */
  87        for (vec = 0; vec < IRQ_MAX; vec++) {
  88                irq_vecs[vec].handler = NULL;
  89                irq_vecs[vec].arg = NULL;
  90                irq_vecs[vec].count = 0;
  91        }
  92
  93#ifdef CONFIG_4xx
  94        /*
  95         * Init PIT
  96         */
  97#if defined(CONFIG_440)
  98        val = mfspr( SPRN_TCR );
  99        val &= (~0x04400000);           /* clear DIS & ARE */
 100        mtspr( SPRN_TCR, val );
 101        mtspr( SPRN_DEC, 0 );           /* Prevent exception after TSR clear*/
 102        mtspr( SPRN_DECAR, 0 );         /* clear reload */
 103        mtspr( SPRN_TSR, 0x08000000 );  /* clear DEC status */
 104        val = gd->bd->bi_intfreq/1000;  /* 1 msec */
 105        mtspr( SPRN_DECAR, val );               /* Set auto-reload value */
 106        mtspr( SPRN_DEC, val );         /* Set inital val */
 107#else
 108        set_pit(gd->bd->bi_intfreq / 1000);
 109#endif
 110#endif  /* CONFIG_4xx */
 111
 112#ifdef CONFIG_ADCIOP
 113        /*
 114         * Init PIT
 115         */
 116        set_pit(66000);
 117#endif
 118
 119        /*
 120         * Enable PIT
 121         */
 122        val = mfspr(SPRN_TCR);
 123        val |= 0x04400000;
 124        mtspr(SPRN_TCR, val);
 125
 126        /*
 127         * Set EVPR to 0
 128         */
 129        set_evpr(0x00000000);
 130
 131        /*
 132         * Call uic or xilinx_irq pic_enable
 133         */
 134        pic_enable();
 135
 136        return (0);
 137}
 138
 139void timer_interrupt_cpu(struct pt_regs *regs)
 140{
 141        /* nothing to do here */
 142        return;
 143}
 144
 145void interrupt_run_handler(int vec)
 146{
 147        irq_vecs[vec].count++;
 148
 149        if (irq_vecs[vec].handler != NULL) {
 150                /* call isr */
 151                (*irq_vecs[vec].handler) (irq_vecs[vec].arg);
 152        } else {
 153                pic_irq_disable(vec);
 154                printf("Masking bogus interrupt vector %d\n", vec);
 155        }
 156
 157        pic_irq_ack(vec);
 158        return;
 159}
 160
 161void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
 162{
 163        /*
 164         * Print warning when replacing with a different irq vector
 165         */
 166        if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
 167                printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
 168                       vec, (uint) handler, (uint) irq_vecs[vec].handler);
 169        }
 170        irq_vecs[vec].handler = handler;
 171        irq_vecs[vec].arg = arg;
 172
 173        pic_irq_enable(vec);
 174        return;
 175}
 176
 177void irq_free_handler(int vec)
 178{
 179        debug("Free interrupt for vector %d ==> %p\n",
 180              vec, irq_vecs[vec].handler);
 181
 182        pic_irq_disable(vec);
 183
 184        irq_vecs[vec].handler = NULL;
 185        irq_vecs[vec].arg = NULL;
 186        return;
 187}
 188
 189#if defined(CONFIG_CMD_IRQ)
 190int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 191{
 192        int vec;
 193
 194        printf ("Interrupt-Information:\n");
 195        printf ("Nr  Routine   Arg       Count\n");
 196
 197        for (vec = 0; vec < IRQ_MAX; vec++) {
 198                if (irq_vecs[vec].handler != NULL) {
 199                        printf ("%02d  %08lx  %08lx  %d\n",
 200                                vec,
 201                                (ulong)irq_vecs[vec].handler,
 202                                (ulong)irq_vecs[vec].arg,
 203                                irq_vecs[vec].count);
 204                }
 205        }
 206
 207        return 0;
 208}
 209#endif
 210