linux/arch/arm/mach-s3c24xx/bast-irq.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   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#include <linux/init.h>
   9#include <linux/module.h>
  10#include <linux/ioport.h>
  11#include <linux/device.h>
  12#include <linux/io.h>
  13
  14#include <asm/irq.h>
  15#include <asm/mach-types.h>
  16#include <asm/mach/irq.h>
  17
  18#include <mach/hardware.h>
  19#include <mach/regs-irq.h>
  20
  21#include "bast.h"
  22
  23#define irqdbf(x...)
  24#define irqdbf2(x...)
  25
  26/* handle PC104 ISA interrupts from the system CPLD */
  27
  28/* table of ISA irq nos to the relevant mask... zero means
  29 * the irq is not implemented
  30*/
  31static const unsigned char bast_pc104_irqmasks[] = {
  32        0,   /* 0 */
  33        0,   /* 1 */
  34        0,   /* 2 */
  35        1,   /* 3 */
  36        0,   /* 4 */
  37        2,   /* 5 */
  38        0,   /* 6 */
  39        4,   /* 7 */
  40        0,   /* 8 */
  41        0,   /* 9 */
  42        8,   /* 10 */
  43        0,   /* 11 */
  44        0,   /* 12 */
  45        0,   /* 13 */
  46        0,   /* 14 */
  47        0,   /* 15 */
  48};
  49
  50static const unsigned char bast_pc104_irqs[] = { 3, 5, 7, 10 };
  51
  52static void
  53bast_pc104_mask(struct irq_data *data)
  54{
  55        unsigned long temp;
  56
  57        temp = __raw_readb(BAST_VA_PC104_IRQMASK);
  58        temp &= ~bast_pc104_irqmasks[data->irq];
  59        __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
  60}
  61
  62static void
  63bast_pc104_maskack(struct irq_data *data)
  64{
  65        struct irq_desc *desc = irq_desc + BAST_IRQ_ISA;
  66
  67        bast_pc104_mask(data);
  68        desc->irq_data.chip->irq_ack(&desc->irq_data);
  69}
  70
  71static void
  72bast_pc104_unmask(struct irq_data *data)
  73{
  74        unsigned long temp;
  75
  76        temp = __raw_readb(BAST_VA_PC104_IRQMASK);
  77        temp |= bast_pc104_irqmasks[data->irq];
  78        __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
  79}
  80
  81static struct irq_chip  bast_pc104_chip = {
  82        .irq_mask       = bast_pc104_mask,
  83        .irq_unmask     = bast_pc104_unmask,
  84        .irq_ack        = bast_pc104_maskack
  85};
  86
  87static void bast_irq_pc104_demux(struct irq_desc *desc)
  88{
  89        unsigned int stat;
  90        unsigned int irqno;
  91        int i;
  92
  93        stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
  94
  95        if (unlikely(stat == 0)) {
  96                /* ack if we get an irq with nothing (ie, startup) */
  97
  98                desc = irq_desc + BAST_IRQ_ISA;
  99                desc->irq_data.chip->irq_ack(&desc->irq_data);
 100        } else {
 101                /* handle the IRQ */
 102
 103                for (i = 0; stat != 0; i++, stat >>= 1) {
 104                        if (stat & 1) {
 105                                irqno = bast_pc104_irqs[i];
 106                                generic_handle_irq(irqno);
 107                        }
 108                }
 109        }
 110}
 111
 112static __init int bast_irq_init(void)
 113{
 114        unsigned int i;
 115
 116        if (machine_is_bast()) {
 117                printk(KERN_INFO "BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics\n");
 118
 119                /* zap all the IRQs */
 120
 121                __raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
 122
 123                irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux);
 124
 125                /* register our IRQs */
 126
 127                for (i = 0; i < 4; i++) {
 128                        unsigned int irqno = bast_pc104_irqs[i];
 129
 130                        irq_set_chip_and_handler(irqno, &bast_pc104_chip,
 131                                                 handle_level_irq);
 132                        irq_clear_status_flags(irqno, IRQ_NOREQUEST);
 133                }
 134        }
 135
 136        return 0;
 137}
 138
 139arch_initcall(bast_irq_init);
 140