linux-bk/arch/sh/cchips/voyagergx/irq.c
<<
>>
Prefs
   1/* -------------------------------------------------------------------- */
   2/* setup_voyagergx.c:                                                     */
   3/* -------------------------------------------------------------------- */
   4/*  This program is free software; you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 2 of the License, or
   7    (at your option) any later version.
   8
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13
  14    You should have received a copy of the GNU General Public License
  15    along with this program; if not, write to the Free Software
  16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17
  18    Copyright 2003 (c) Lineo uSolutions,Inc.
  19*/
  20/* -------------------------------------------------------------------- */
  21
  22#undef DEBUG
  23
  24#include <linux/config.h>
  25#include <linux/sched.h>
  26#include <linux/module.h>
  27#include <linux/kernel.h>
  28#include <linux/param.h>
  29#include <linux/ioport.h>
  30#include <linux/interrupt.h>
  31#include <linux/init.h>
  32#include <linux/irq.h>
  33
  34#include <asm/io.h>
  35#include <asm/irq.h>
  36#include <asm/rts7751r2d/rts7751r2d.h>
  37#include <asm/rts7751r2d/voyagergx_reg.h>
  38
  39static void disable_voyagergx_irq(unsigned int irq)
  40{
  41        unsigned long flags, val;
  42        unsigned long  mask = 1 << (irq - VOYAGER_IRQ_BASE);
  43
  44        pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
  45        local_irq_save(flags);
  46        val = inl(VOYAGER_INT_MASK);
  47        val &= ~mask;
  48        outl(val, VOYAGER_INT_MASK);
  49        local_irq_restore(flags);
  50}
  51
  52
  53static void enable_voyagergx_irq(unsigned int irq)
  54{
  55        unsigned long flags, val;
  56        unsigned long  mask = 1 << (irq - VOYAGER_IRQ_BASE);
  57
  58        pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
  59        local_irq_save(flags);
  60        val = inl(VOYAGER_INT_MASK);
  61        val |= mask;
  62        outl(val, VOYAGER_INT_MASK);
  63        local_irq_restore(flags);
  64}
  65
  66
  67static void mask_and_ack_voyagergx(unsigned int irq)
  68{
  69        disable_voyagergx_irq(irq);
  70}
  71
  72static void end_voyagergx_irq(unsigned int irq)
  73{
  74        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  75                enable_voyagergx_irq(irq);
  76}
  77
  78static unsigned int startup_voyagergx_irq(unsigned int irq)
  79{
  80        enable_voyagergx_irq(irq);
  81        return 0;
  82}
  83
  84static void shutdown_voyagergx_irq(unsigned int irq)
  85{
  86        disable_voyagergx_irq(irq);
  87}
  88
  89static struct hw_interrupt_type voyagergx_irq_type = {
  90        "VOYAGERGX-IRQ",
  91        startup_voyagergx_irq,
  92        shutdown_voyagergx_irq,
  93        enable_voyagergx_irq,
  94        disable_voyagergx_irq,
  95        mask_and_ack_voyagergx,
  96        end_voyagergx_irq,
  97};
  98
  99static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 100{
 101        printk(KERN_INFO
 102               "VoyagerGX: spurious interrupt, status: 0x%x\n",
 103                        inl(INT_STATUS));
 104        return IRQ_HANDLED;
 105}
 106
 107
 108/*====================================================*/
 109
 110static struct {
 111        int (*func)(int, void *);
 112        void *dev;
 113} voyagergx_demux[VOYAGER_IRQ_NUM];
 114
 115void voyagergx_register_irq_demux(int irq,
 116                int (*demux)(int irq, void *dev), void *dev)
 117{
 118        voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
 119        voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
 120}
 121
 122void voyagergx_unregister_irq_demux(int irq)
 123{
 124        voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
 125}
 126
 127int voyagergx_irq_demux(int irq)
 128{
 129
 130        if (irq == IRQ_VOYAGER ) {
 131                unsigned long i = 0, bit __attribute__ ((unused));
 132                unsigned long val  = inl(INT_STATUS);
 133#if 1
 134                if ( val & ( 1 << 1 )){
 135                        i = 1;
 136                } else if ( val & ( 1 << 2 )){
 137                        i = 2;
 138                } else if ( val & ( 1 << 6 )){
 139                        i = 6;
 140                } else if( val & ( 1 << 10 )){
 141                        i = 10;
 142                } else if( val & ( 1 << 11 )){
 143                        i = 11;
 144                } else if( val & ( 1 << 12 )){
 145                        i = 12;
 146                } else if( val & ( 1 << 17 )){
 147                        i = 17;
 148                } else {
 149                        printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
 150                }
 151                pr_debug("voyagergx_irq_demux %d \n", i);
 152#else
 153                for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++)
 154                        if (val & bit)
 155                                break;
 156#endif
 157                if (i < VOYAGER_IRQ_NUM) {
 158                        irq = VOYAGER_IRQ_BASE + i;
 159                        if (voyagergx_demux[i].func != 0)
 160                                irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev);
 161                }
 162        }
 163        return irq;
 164}
 165
 166static struct irqaction irq0  = { voyagergx_interrupt, SA_INTERRUPT, 0, "VOYAGERGX", NULL, NULL};
 167
 168void __init setup_voyagergx_irq(void)
 169{
 170        int i, flag;
 171
 172        printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n",
 173               VOYAGER_BASE,
 174               IRQ_VOYAGER,
 175               VOYAGER_IRQ_BASE,
 176               VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1);
 177
 178        for (i=0; i<VOYAGER_IRQ_NUM; i++) {
 179                flag = 0;
 180                switch (VOYAGER_IRQ_BASE + i) {
 181                case VOYAGER_USBH_IRQ:
 182                case VOYAGER_8051_IRQ:
 183                case VOYAGER_UART0_IRQ:
 184                case VOYAGER_UART1_IRQ:
 185                case VOYAGER_AC97_IRQ:
 186                        flag = 1;
 187                }
 188                if (flag == 1)
 189                        irq_desc[VOYAGER_IRQ_BASE + i].handler = &voyagergx_irq_type;
 190        }
 191
 192        setup_irq(IRQ_VOYAGER, &irq0);
 193}
 194
 195
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.