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 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 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
 104bast_irq_pc104_demux(unsigned int irq,
 105                     struct irq_desc *desc)
 106{
 107        unsigned int stat;
 108        unsigned int irqno;
 109        int i;
 110
 111        stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
 112
 113        if (unlikely(stat == 0)) {
 114                /* ack if we get an irq with nothing (ie, startup) */
 115
 116                desc = irq_desc + BAST_IRQ_ISA;
 117                desc->irq_data.chip->irq_ack(&desc->irq_data);
 118        } else {
 119                /* handle the IRQ */
 120
 121                for (i = 0; stat != 0; i++, stat >>= 1) {
 122                        if (stat & 1) {
 123                                irqno = bast_pc104_irqs[i];
 124                                generic_handle_irq(irqno);
 125                        }
 126                }
 127        }
 128}
 129
 130static __init int bast_irq_init(void)
 131{
 132        unsigned int i;
 133
 134        if (machine_is_bast()) {
 135                printk(KERN_INFO "BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics\n");
 136
 137                /* zap all the IRQs */
 138
 139                __raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
 140
 141                irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux);
 142
 143                /* register our IRQs */
 144
 145                for (i = 0; i < 4; i++) {
 146                        unsigned int irqno = bast_pc104_irqs[i];
 147
 148                        irq_set_chip_and_handler(irqno, &bast_pc104_chip,
 149                                                 handle_level_irq);
 150                        set_irq_flags(irqno, IRQF_VALID);
 151                }
 152        }
 153
 154        return 0;
 155}
 156
 157arch_initcall(bast_irq_init);
 158