linux/arch/h8300/kernel/irq.c
<<
>>
Prefs
   1/*
   2 * linux/arch/h8300/kernel/irq.c
   3 *
   4 * Copyright 2007 Yoshinori Sato <ysato@users.sourceforge.jp>
   5 */
   6
   7#include <linux/module.h>
   8#include <linux/types.h>
   9#include <linux/kernel.h>
  10#include <linux/sched.h>
  11#include <linux/kernel_stat.h>
  12#include <linux/seq_file.h>
  13#include <linux/init.h>
  14#include <linux/random.h>
  15#include <linux/bootmem.h>
  16#include <linux/irq.h>
  17#include <linux/interrupt.h>
  18
  19#include <asm/traps.h>
  20#include <asm/io.h>
  21#include <asm/setup.h>
  22#include <asm/errno.h>
  23
  24/*#define DEBUG*/
  25
  26extern unsigned long *interrupt_redirect_table;
  27extern const int h8300_saved_vectors[];
  28extern const h8300_vector h8300_trap_table[];
  29int h8300_enable_irq_pin(unsigned int irq);
  30void h8300_disable_irq_pin(unsigned int irq);
  31
  32#define CPU_VECTOR ((unsigned long *)0x000000)
  33#define ADDR_MASK (0xffffff)
  34
  35static inline int is_ext_irq(unsigned int irq)
  36{
  37        return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS));
  38}
  39
  40static void h8300_enable_irq(struct irq_data *data)
  41{
  42        if (is_ext_irq(data->irq))
  43                IER_REGS |= 1 << (data->irq - EXT_IRQ0);
  44}
  45
  46static void h8300_disable_irq(struct irq_data *data)
  47{
  48        if (is_ext_irq(data->irq))
  49                IER_REGS &= ~(1 << (data->irq - EXT_IRQ0));
  50}
  51
  52static unsigned int h8300_startup_irq(struct irq_data *data)
  53{
  54        if (is_ext_irq(data->irq))
  55                return h8300_enable_irq_pin(data->irq);
  56        else
  57                return 0;
  58}
  59
  60static void h8300_shutdown_irq(struct irq_data *data)
  61{
  62        if (is_ext_irq(data->irq))
  63                h8300_disable_irq_pin(data->irq);
  64}
  65
  66/*
  67 * h8300 interrupt controller implementation
  68 */
  69struct irq_chip h8300irq_chip = {
  70        .name           = "H8300-INTC",
  71        .irq_startup    = h8300_startup_irq,
  72        .irq_shutdown   = h8300_shutdown_irq,
  73        .irq_enable     = h8300_enable_irq,
  74        .irq_disable    = h8300_disable_irq,
  75};
  76
  77#if defined(CONFIG_RAMKERNEL)
  78static unsigned long __init *get_vector_address(void)
  79{
  80        unsigned long *rom_vector = CPU_VECTOR;
  81        unsigned long base,tmp;
  82        int vec_no;
  83
  84        base = rom_vector[EXT_IRQ0] & ADDR_MASK;
  85
  86        /* check romvector format */
  87        for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
  88                if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
  89                        return NULL;
  90        }
  91
  92        /* ramvector base address */
  93        base -= EXT_IRQ0*4;
  94
  95        /* writerble check */
  96        tmp = ~(*(volatile unsigned long *)base);
  97        (*(volatile unsigned long *)base) = tmp;
  98        if ((*(volatile unsigned long *)base) != tmp)
  99                return NULL;
 100        return (unsigned long *)base;
 101}
 102
 103static void __init setup_vector(void)
 104{
 105        int i;
 106        unsigned long *ramvec,*ramvec_p;
 107        const h8300_vector *trap_entry;
 108        const int *saved_vector;
 109
 110        ramvec = get_vector_address();
 111        if (ramvec == NULL)
 112                panic("interrupt vector serup failed.");
 113        else
 114                printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
 115
 116        /* create redirect table */
 117        ramvec_p = ramvec;
 118        trap_entry = h8300_trap_table;
 119        saved_vector = h8300_saved_vectors;
 120        for ( i = 0; i < NR_IRQS; i++) {
 121                if (i == *saved_vector) {
 122                        ramvec_p++;
 123                        saved_vector++;
 124                } else {
 125                        if ( i < NR_TRAPS ) {
 126                                if (*trap_entry)
 127                                        *ramvec_p = VECTOR(*trap_entry);
 128                                ramvec_p++;
 129                                trap_entry++;
 130                        } else
 131                                *ramvec_p++ = REDIRECT(interrupt_entry);
 132                }
 133        }
 134        interrupt_redirect_table = ramvec;
 135#ifdef DEBUG
 136        ramvec_p = ramvec;
 137        for (i = 0; i < NR_IRQS; i++) {
 138                if ((i % 8) == 0)
 139                        printk(KERN_DEBUG "\n%p: ",ramvec_p);
 140                printk(KERN_DEBUG "%p ",*ramvec_p);
 141                ramvec_p++;
 142        }
 143        printk(KERN_DEBUG "\n");
 144#endif
 145}
 146#else
 147#define setup_vector() do { } while(0)
 148#endif
 149
 150void __init init_IRQ(void)
 151{
 152        int c;
 153
 154        setup_vector();
 155
 156        for (c = 0; c < NR_IRQS; c++)
 157                irq_set_chip_and_handler(c, &h8300irq_chip, handle_simple_irq);
 158}
 159
 160asmlinkage void do_IRQ(int irq)
 161{
 162        irq_enter();
 163        generic_handle_irq(irq);
 164        irq_exit();
 165}
 166