linux/arch/arm/mach-s3c24xx/bast-irq.c
<<
>>
Prefs
   1/* linux/arch/arm/mach-s3c2410/bast-irq.c
   2 *
   3 * Copyright 2003-2005 Simtec Electronics
   4 *   Ben Dooks <ben@simtec.co.uk>
   5 *
   6 * http://www.simtec.co.uk/products/EB2410ITX/
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21*/
  22
  23
  24#include <linux/init.h>
  25#include <linux/module.h>
  26#include <linux/ioport.h>
  27#include <linux/device.h>
  28#include <linux/io.h>
  29
  30#include <asm/irq.h>
  31#include <asm/mach-types.h>
  32#include <asm/mach/irq.h>
  33
  34#include <mach/hardware.h>
  35#include <mach/regs-irq.h>
  36
  37#include "bast.h"
  38
  39#define irqdbf(x...)
  40#define irqdbf2(x...)
  41
  42/* handle PC104 ISA interrupts from the system CPLD */
  43
  44/* table of ISA irq nos to the relevant mask... zero means
  45 * the irq is not implemented
  46*/
  47static const unsigned char bast_pc104_irqmasks[] = {
  48        0,   /* 0 */
  49        0,   /* 1 */
  50        0,   /* 2 */
  51        1,   /* 3 */
  52        0,   /* 4 */
  53        2,   /* 5 */
  54        0,   /* 6 */
  55        4,   /* 7 */
  56        0,   /* 8 */
  57        0,   /* 9 */
  58        8,   /* 10 */
  59        0,   /* 11 */
  60        0,   /* 12 */
  61        0,   /* 13 */
  62        0,   /* 14 */
  63        0,   /* 15 */
  64};
  65
  66static const unsigned char bast_pc104_irqs[] = { 3, 5, 7, 10 };
  67
  68static void
  69bast_pc104_mask(struct irq_data *data)
  70{
  71        unsigned long temp;
  72
  73        temp = __raw_readb(BAST_VA_PC104_IRQMASK);
  74        temp &= ~bast_pc104_irqmasks[data->irq];
  75        __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
  76}
  77
  78static void
  79bast_pc104_maskack(struct irq_data *data)
  80{
  81        struct irq_desc *desc = irq_desc + BAST_IRQ_ISA;
  82
  83        bast_pc104_mask(data);
  84        desc->irq_data.chip->irq_ack(&desc->irq_data);
  85}
  86
  87static void
  88bast_pc104_unmask(struct irq_data *data)
  89{
  90        unsigned long temp;
  91
  92        temp = __raw_readb(BAST_VA_PC104_IRQMASK);
  93        temp |= bast_pc104_irqmasks[data->irq];
  94        __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
  95}
  96
  97static struct irq_chip  bast_pc104_chip = {
  98        .irq_mask       = bast_pc104_mask,
  99        .irq_unmask     = bast_pc104_unmask,
 100        .irq_ack        = bast_pc104_maskack
 101};
 102
 103static void bast_irq_pc104_demux(struct irq_desc *desc)
 104{
 105        unsigned int stat;
 106        unsigned int irqno;
 107        int i;
 108
 109        stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
 110
 111        if (unlikely(stat == 0)) {
 112                /* ack if we get an irq with nothing (ie, startup) */
 113
 114                desc = irq_desc + BAST_IRQ_ISA;
 115                desc->irq_data.chip->irq_ack(&desc->irq_data);
 116        } else {
 117                /* handle the IRQ */
 118
 119                for (i = 0; stat != 0; i++, stat >>= 1) {
 120                        if (stat & 1) {
 121                                irqno = bast_pc104_irqs[i];
 122                                generic_handle_irq(irqno);
 123                        }
 124                }
 125        }
 126}
 127
 128static __init int bast_irq_init(void)
 129{
 130        unsigned int i;
 131
 132        if (machine_is_bast()) {
 133                printk(KERN_INFO "BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics\n");
 134
 135                /* zap all the IRQs */
 136
 137                __raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
 138
 139                irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux);
 140
 141                /* register our IRQs */
 142
 143                for (i = 0; i < 4; i++) {
 144                        unsigned int irqno = bast_pc104_irqs[i];
 145
 146                        irq_set_chip_and_handler(irqno, &bast_pc104_chip,
 147                                                 handle_level_irq);
 148                        irq_clear_status_flags(irqno, IRQ_NOREQUEST);
 149                }
 150        }
 151
 152        return 0;
 153}
 154
 155arch_initcall(bast_irq_init);
 156