linux/arch/m68knommu/platform/coldfire/intc-2.c
<<
>>
Prefs
   1/*
   2 * intc-1.c
   3 *
   4 * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file COPYING in the main directory of this archive
   8 * for more details.
   9 */
  10
  11#include <linux/types.h>
  12#include <linux/init.h>
  13#include <linux/kernel.h>
  14#include <linux/interrupt.h>
  15#include <linux/irq.h>
  16#include <linux/io.h>
  17#include <asm/coldfire.h>
  18#include <asm/mcfsim.h>
  19#include <asm/traps.h>
  20
  21/*
  22 *      Each vector needs a unique priority and level asscoiated with it.
  23 *      We don't really care so much what they are, we don't rely on the
  24 *      tranditional priority interrupt scheme of the m68k/ColdFire.
  25 */
  26static u8 intc_intpri = 0x36;
  27
  28static void intc_irq_mask(unsigned int irq)
  29{
  30        if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
  31                unsigned long imraddr;
  32                u32 val, imrbit;
  33
  34                irq -= MCFINT_VECBASE;
  35                imraddr = MCF_IPSBAR;
  36                imraddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
  37                imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
  38                imrbit = 0x1 << (irq & 0x1f);
  39
  40                val = __raw_readl(imraddr);
  41                __raw_writel(val | imrbit, imraddr);
  42        }
  43}
  44
  45static void intc_irq_unmask(unsigned int irq)
  46{
  47        if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
  48                unsigned long intaddr, imraddr, icraddr;
  49                u32 val, imrbit;
  50
  51                irq -= MCFINT_VECBASE;
  52                intaddr = MCF_IPSBAR;
  53                intaddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
  54                imraddr = intaddr + ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
  55                icraddr = intaddr + MCFINTC_ICR0 + (irq & 0x3f);
  56                imrbit = 0x1 << (irq & 0x1f);
  57
  58                /* Don't set the "maskall" bit! */
  59                if ((irq & 0x20) == 0)
  60                        imrbit |= 0x1;
  61
  62                if (__raw_readb(icraddr) == 0)
  63                        __raw_writeb(intc_intpri--, icraddr);
  64
  65                val = __raw_readl(imraddr);
  66                __raw_writel(val & ~imrbit, imraddr);
  67        }
  68}
  69
  70static struct irq_chip intc_irq_chip = {
  71        .name           = "CF-INTC",
  72        .mask           = intc_irq_mask,
  73        .unmask         = intc_irq_unmask,
  74};
  75
  76void __init init_IRQ(void)
  77{
  78        int irq;
  79
  80        init_vectors();
  81
  82        /* Mask all interrupt sources */
  83        __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
  84        __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL);
  85
  86        for (irq = 0; (irq < NR_IRQS); irq++) {
  87                irq_desc[irq].status = IRQ_DISABLED;
  88                irq_desc[irq].action = NULL;
  89                irq_desc[irq].depth = 1;
  90                irq_desc[irq].chip = &intc_irq_chip;
  91        }
  92}
  93
  94