linux/arch/arm/mach-ns9xxx/irq.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-ns9xxx/irq.c
   3 *
   4 * Copyright (C) 2006,2007 by Digi International Inc.
   5 * All rights reserved.
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License version 2 as published by
   9 * the Free Software Foundation.
  10 */
  11#include <linux/interrupt.h>
  12#include <linux/kernel_stat.h>
  13#include <linux/io.h>
  14#include <asm/mach/irq.h>
  15#include <mach/regs-sys-common.h>
  16#include <mach/irqs.h>
  17#include <mach/board.h>
  18
  19#include "generic.h"
  20
  21/* simple interrupt prio table: prio(x) < prio(y) <=> x < y */
  22#define irq2prio(i) (i)
  23#define prio2irq(p) (p)
  24
  25static void ns9xxx_mask_irq(unsigned int irq)
  26{
  27        /* XXX: better use cpp symbols */
  28        int prio = irq2prio(irq);
  29        u32 ic = __raw_readl(SYS_IC(prio / 4));
  30        ic &= ~(1 << (7 + 8 * (3 - (prio & 3))));
  31        __raw_writel(ic, SYS_IC(prio / 4));
  32}
  33
  34static void ns9xxx_ack_irq(unsigned int irq)
  35{
  36        __raw_writel(0, SYS_ISRADDR);
  37}
  38
  39static void ns9xxx_maskack_irq(unsigned int irq)
  40{
  41        ns9xxx_mask_irq(irq);
  42        ns9xxx_ack_irq(irq);
  43}
  44
  45static void ns9xxx_unmask_irq(unsigned int irq)
  46{
  47        /* XXX: better use cpp symbols */
  48        int prio = irq2prio(irq);
  49        u32 ic = __raw_readl(SYS_IC(prio / 4));
  50        ic |= 1 << (7 + 8 * (3 - (prio & 3)));
  51        __raw_writel(ic, SYS_IC(prio / 4));
  52}
  53
  54static struct irq_chip ns9xxx_chip = {
  55        .ack            = ns9xxx_ack_irq,
  56        .mask           = ns9xxx_mask_irq,
  57        .mask_ack       = ns9xxx_maskack_irq,
  58        .unmask         = ns9xxx_unmask_irq,
  59};
  60
  61#if 0
  62#define handle_irq handle_level_irq
  63#else
  64static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
  65{
  66        struct irqaction *action;
  67        irqreturn_t action_ret;
  68
  69        spin_lock(&desc->lock);
  70
  71        BUG_ON(desc->status & IRQ_INPROGRESS);
  72
  73        desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
  74        kstat_incr_irqs_this_cpu(irq, desc);
  75
  76        action = desc->action;
  77        if (unlikely(!action || (desc->status & IRQ_DISABLED)))
  78                goto out_mask;
  79
  80        desc->status |= IRQ_INPROGRESS;
  81        spin_unlock(&desc->lock);
  82
  83        action_ret = handle_IRQ_event(irq, action);
  84
  85        /* XXX: There is no direct way to access noirqdebug, so check
  86         * unconditionally for spurious irqs...
  87         * Maybe this function should go to kernel/irq/chip.c? */
  88        note_interrupt(irq, desc, action_ret);
  89
  90        spin_lock(&desc->lock);
  91        desc->status &= ~IRQ_INPROGRESS;
  92
  93        if (desc->status & IRQ_DISABLED)
  94out_mask:
  95                desc->chip->mask(irq);
  96
  97        /* ack unconditionally to unmask lower prio irqs */
  98        desc->chip->ack(irq);
  99
 100        spin_unlock(&desc->lock);
 101}
 102#define handle_irq handle_prio_irq
 103#endif
 104
 105void __init ns9xxx_init_irq(void)
 106{
 107        int i;
 108
 109        /* disable all IRQs */
 110        for (i = 0; i < 8; ++i)
 111                __raw_writel(prio2irq(4 * i) << 24 |
 112                                prio2irq(4 * i + 1) << 16 |
 113                                prio2irq(4 * i + 2) << 8 |
 114                                prio2irq(4 * i + 3),
 115                                SYS_IC(i));
 116
 117        for (i = 0; i < 32; ++i)
 118                __raw_writel(prio2irq(i), SYS_IVA(i));
 119
 120        for (i = 0; i <= 31; ++i) {
 121                set_irq_chip(i, &ns9xxx_chip);
 122                set_irq_handler(i, handle_irq);
 123                set_irq_flags(i, IRQF_VALID);
 124        }
 125}
 126