linux/arch/arm/mach-davinci/irq.c
<<
>>
Prefs
   1/*
   2 * Interrupt handler for DaVinci boards.
   3 *
   4 * Copyright (C) 2006 Texas Instruments.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 *
  20 */
  21#include <linux/kernel.h>
  22#include <linux/init.h>
  23#include <linux/interrupt.h>
  24#include <linux/irq.h>
  25
  26#include <asm/hardware.h>
  27#include <asm/io.h>
  28#include <asm/mach/irq.h>
  29
  30#define IRQ_BIT(irq)            ((irq) & 0x1f)
  31
  32#define FIQ_REG0_OFFSET         0x0000
  33#define FIQ_REG1_OFFSET         0x0004
  34#define IRQ_REG0_OFFSET         0x0008
  35#define IRQ_REG1_OFFSET         0x000C
  36#define IRQ_ENT_REG0_OFFSET     0x0018
  37#define IRQ_ENT_REG1_OFFSET     0x001C
  38#define IRQ_INCTL_REG_OFFSET    0x0020
  39#define IRQ_EABASE_REG_OFFSET   0x0024
  40#define IRQ_INTPRI0_REG_OFFSET  0x0030
  41#define IRQ_INTPRI7_REG_OFFSET  0x004C
  42
  43static inline unsigned int davinci_irq_readl(int offset)
  44{
  45        return davinci_readl(DAVINCI_ARM_INTC_BASE + offset);
  46}
  47
  48static inline void davinci_irq_writel(unsigned long value, int offset)
  49{
  50        davinci_writel(value, DAVINCI_ARM_INTC_BASE + offset);
  51}
  52
  53/* Disable interrupt */
  54static void davinci_mask_irq(unsigned int irq)
  55{
  56        unsigned int mask;
  57        u32 l;
  58
  59        mask = 1 << IRQ_BIT(irq);
  60
  61        if (irq > 31) {
  62                l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
  63                l &= ~mask;
  64                davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
  65        } else {
  66                l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
  67                l &= ~mask;
  68                davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
  69        }
  70}
  71
  72/* Enable interrupt */
  73static void davinci_unmask_irq(unsigned int irq)
  74{
  75        unsigned int mask;
  76        u32 l;
  77
  78        mask = 1 << IRQ_BIT(irq);
  79
  80        if (irq > 31) {
  81                l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
  82                l |= mask;
  83                davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
  84        } else {
  85                l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
  86                l |= mask;
  87                davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
  88        }
  89}
  90
  91/* EOI interrupt */
  92static void davinci_ack_irq(unsigned int irq)
  93{
  94        unsigned int mask;
  95
  96        mask = 1 << IRQ_BIT(irq);
  97
  98        if (irq > 31)
  99                davinci_irq_writel(mask, IRQ_REG1_OFFSET);
 100        else
 101                davinci_irq_writel(mask, IRQ_REG0_OFFSET);
 102}
 103
 104static struct irq_chip davinci_irq_chip_0 = {
 105        .name   = "AINTC",
 106        .ack    = davinci_ack_irq,
 107        .mask   = davinci_mask_irq,
 108        .unmask = davinci_unmask_irq,
 109};
 110
 111
 112/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
 113static const u8 default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
 114        [IRQ_VDINT0]            = 2,
 115        [IRQ_VDINT1]            = 6,
 116        [IRQ_VDINT2]            = 6,
 117        [IRQ_HISTINT]           = 6,
 118        [IRQ_H3AINT]            = 6,
 119        [IRQ_PRVUINT]           = 6,
 120        [IRQ_RSZINT]            = 6,
 121        [7]                     = 7,
 122        [IRQ_VENCINT]           = 6,
 123        [IRQ_ASQINT]            = 6,
 124        [IRQ_IMXINT]            = 6,
 125        [IRQ_VLCDINT]           = 6,
 126        [IRQ_USBINT]            = 4,
 127        [IRQ_EMACINT]           = 4,
 128        [14]                    = 7,
 129        [15]                    = 7,
 130        [IRQ_CCINT0]            = 5,    /* dma */
 131        [IRQ_CCERRINT]          = 5,    /* dma */
 132        [IRQ_TCERRINT0]         = 5,    /* dma */
 133        [IRQ_TCERRINT]          = 5,    /* dma */
 134        [IRQ_PSCIN]             = 7,
 135        [21]                    = 7,
 136        [IRQ_IDE]               = 4,
 137        [23]                    = 7,
 138        [IRQ_MBXINT]            = 7,
 139        [IRQ_MBRINT]            = 7,
 140        [IRQ_MMCINT]            = 7,
 141        [IRQ_SDIOINT]           = 7,
 142        [28]                    = 7,
 143        [IRQ_DDRINT]            = 7,
 144        [IRQ_AEMIFINT]          = 7,
 145        [IRQ_VLQINT]            = 4,
 146        [IRQ_TINT0_TINT12]      = 2,    /* clockevent */
 147        [IRQ_TINT0_TINT34]      = 2,    /* clocksource */
 148        [IRQ_TINT1_TINT12]      = 7,    /* DSP timer */
 149        [IRQ_TINT1_TINT34]      = 7,    /* system tick */
 150        [IRQ_PWMINT0]           = 7,
 151        [IRQ_PWMINT1]           = 7,
 152        [IRQ_PWMINT2]           = 7,
 153        [IRQ_I2C]               = 3,
 154        [IRQ_UARTINT0]          = 3,
 155        [IRQ_UARTINT1]          = 3,
 156        [IRQ_UARTINT2]          = 3,
 157        [IRQ_SPINT0]            = 3,
 158        [IRQ_SPINT1]            = 3,
 159        [45]                    = 7,
 160        [IRQ_DSP2ARM0]          = 4,
 161        [IRQ_DSP2ARM1]          = 4,
 162        [IRQ_GPIO0]             = 7,
 163        [IRQ_GPIO1]             = 7,
 164        [IRQ_GPIO2]             = 7,
 165        [IRQ_GPIO3]             = 7,
 166        [IRQ_GPIO4]             = 7,
 167        [IRQ_GPIO5]             = 7,
 168        [IRQ_GPIO6]             = 7,
 169        [IRQ_GPIO7]             = 7,
 170        [IRQ_GPIOBNK0]          = 7,
 171        [IRQ_GPIOBNK1]          = 7,
 172        [IRQ_GPIOBNK2]          = 7,
 173        [IRQ_GPIOBNK3]          = 7,
 174        [IRQ_GPIOBNK4]          = 7,
 175        [IRQ_COMMTX]            = 7,
 176        [IRQ_COMMRX]            = 7,
 177        [IRQ_EMUINT]            = 7,
 178};
 179
 180/* ARM Interrupt Controller Initialization */
 181void __init davinci_irq_init(void)
 182{
 183        unsigned i;
 184        const u8 *priority = default_priorities;
 185
 186        /* Clear all interrupt requests */
 187        davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
 188        davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
 189        davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
 190        davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
 191
 192        /* Disable all interrupts */
 193        davinci_irq_writel(0x0, IRQ_ENT_REG0_OFFSET);
 194        davinci_irq_writel(0x0, IRQ_ENT_REG1_OFFSET);
 195
 196        /* Interrupts disabled immediately, IRQ entry reflects all */
 197        davinci_irq_writel(0x0, IRQ_INCTL_REG_OFFSET);
 198
 199        /* we don't use the hardware vector table, just its entry addresses */
 200        davinci_irq_writel(0, IRQ_EABASE_REG_OFFSET);
 201
 202        /* Clear all interrupt requests */
 203        davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
 204        davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
 205        davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
 206        davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
 207
 208        for (i = IRQ_INTPRI0_REG_OFFSET; i <= IRQ_INTPRI7_REG_OFFSET; i += 4) {
 209                unsigned        j;
 210                u32             pri;
 211
 212                for (j = 0, pri = 0; j < 32; j += 4, priority++)
 213                        pri |= (*priority & 0x07) << j;
 214                davinci_irq_writel(pri, i);
 215        }
 216
 217        /* set up genirq dispatch for ARM INTC */
 218        for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
 219                set_irq_chip(i, &davinci_irq_chip_0);
 220                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 221                if (i != IRQ_TINT1_TINT34)
 222                        set_irq_handler(i, handle_edge_irq);
 223                else
 224                        set_irq_handler(i, handle_level_irq);
 225        }
 226}
 227