linux/arch/mips/emma/markeins/irq.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) NEC Electronics Corporation 2004-2006
   3 *
   4 *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
   5 *
   6 *      Copyright 2001 MontaVista Software Inc.
   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#include <linux/init.h>
  23#include <linux/interrupt.h>
  24#include <linux/irq.h>
  25#include <linux/types.h>
  26#include <linux/ptrace.h>
  27#include <linux/delay.h>
  28
  29#include <asm/irq_cpu.h>
  30#include <asm/system.h>
  31#include <asm/mipsregs.h>
  32#include <asm/addrspace.h>
  33#include <asm/bootinfo.h>
  34
  35#include <asm/emma/emma2rh.h>
  36
  37static void emma2rh_irq_enable(unsigned int irq)
  38{
  39        u32 reg_value;
  40        u32 reg_bitmask;
  41        u32 reg_index;
  42
  43        irq -= EMMA2RH_IRQ_BASE;
  44
  45        reg_index = EMMA2RH_BHIF_INT_EN_0 +
  46                    (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32);
  47        reg_value = emma2rh_in32(reg_index);
  48        reg_bitmask = 0x1 << (irq % 32);
  49        emma2rh_out32(reg_index, reg_value | reg_bitmask);
  50}
  51
  52static void emma2rh_irq_disable(unsigned int irq)
  53{
  54        u32 reg_value;
  55        u32 reg_bitmask;
  56        u32 reg_index;
  57
  58        irq -= EMMA2RH_IRQ_BASE;
  59
  60        reg_index = EMMA2RH_BHIF_INT_EN_0 +
  61                    (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32);
  62        reg_value = emma2rh_in32(reg_index);
  63        reg_bitmask = 0x1 << (irq % 32);
  64        emma2rh_out32(reg_index, reg_value & ~reg_bitmask);
  65}
  66
  67struct irq_chip emma2rh_irq_controller = {
  68        .name = "emma2rh_irq",
  69        .ack = emma2rh_irq_disable,
  70        .mask = emma2rh_irq_disable,
  71        .mask_ack = emma2rh_irq_disable,
  72        .unmask = emma2rh_irq_enable,
  73};
  74
  75void emma2rh_irq_init(void)
  76{
  77        u32 i;
  78
  79        for (i = 0; i < NUM_EMMA2RH_IRQ; i++)
  80                set_irq_chip_and_handler_name(EMMA2RH_IRQ_BASE + i,
  81                                              &emma2rh_irq_controller,
  82                                              handle_level_irq, "level");
  83}
  84
  85static void emma2rh_sw_irq_enable(unsigned int irq)
  86{
  87        u32 reg;
  88
  89        irq -= EMMA2RH_SW_IRQ_BASE;
  90
  91        reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
  92        reg |= 1 << irq;
  93        emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
  94}
  95
  96static void emma2rh_sw_irq_disable(unsigned int irq)
  97{
  98        u32 reg;
  99
 100        irq -= EMMA2RH_SW_IRQ_BASE;
 101
 102        reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
 103        reg &= ~(1 << irq);
 104        emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
 105}
 106
 107struct irq_chip emma2rh_sw_irq_controller = {
 108        .name = "emma2rh_sw_irq",
 109        .ack = emma2rh_sw_irq_disable,
 110        .mask = emma2rh_sw_irq_disable,
 111        .mask_ack = emma2rh_sw_irq_disable,
 112        .unmask = emma2rh_sw_irq_enable,
 113};
 114
 115void emma2rh_sw_irq_init(void)
 116{
 117        u32 i;
 118
 119        for (i = 0; i < NUM_EMMA2RH_IRQ_SW; i++)
 120                set_irq_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i,
 121                                              &emma2rh_sw_irq_controller,
 122                                              handle_level_irq, "level");
 123}
 124
 125static void emma2rh_gpio_irq_enable(unsigned int irq)
 126{
 127        u32 reg;
 128
 129        irq -= EMMA2RH_GPIO_IRQ_BASE;
 130
 131        reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
 132        reg |= 1 << irq;
 133        emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
 134}
 135
 136static void emma2rh_gpio_irq_disable(unsigned int irq)
 137{
 138        u32 reg;
 139
 140        irq -= EMMA2RH_GPIO_IRQ_BASE;
 141
 142        reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
 143        reg &= ~(1 << irq);
 144        emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
 145}
 146
 147static void emma2rh_gpio_irq_ack(unsigned int irq)
 148{
 149        irq -= EMMA2RH_GPIO_IRQ_BASE;
 150        emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
 151}
 152
 153static void emma2rh_gpio_irq_mask_ack(unsigned int irq)
 154{
 155        u32 reg;
 156
 157        irq -= EMMA2RH_GPIO_IRQ_BASE;
 158        emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
 159
 160        reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
 161        reg &= ~(1 << irq);
 162        emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
 163}
 164
 165struct irq_chip emma2rh_gpio_irq_controller = {
 166        .name = "emma2rh_gpio_irq",
 167        .ack = emma2rh_gpio_irq_ack,
 168        .mask = emma2rh_gpio_irq_disable,
 169        .mask_ack = emma2rh_gpio_irq_mask_ack,
 170        .unmask = emma2rh_gpio_irq_enable,
 171};
 172
 173void emma2rh_gpio_irq_init(void)
 174{
 175        u32 i;
 176
 177        for (i = 0; i < NUM_EMMA2RH_IRQ_GPIO; i++)
 178                set_irq_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i,
 179                                              &emma2rh_gpio_irq_controller,
 180                                              handle_edge_irq, "edge");
 181}
 182
 183static struct irqaction irq_cascade = {
 184           .handler = no_action,
 185           .flags = 0,
 186           .name = "cascade",
 187           .dev_id = NULL,
 188           .next = NULL,
 189};
 190
 191/*
 192 * the first level int-handler will jump here if it is a emma2rh irq
 193 */
 194void emma2rh_irq_dispatch(void)
 195{
 196        u32 intStatus;
 197        u32 bitmask;
 198        u32 i;
 199
 200        intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0) &
 201                    emma2rh_in32(EMMA2RH_BHIF_INT_EN_0);
 202
 203#ifdef EMMA2RH_SW_CASCADE
 204        if (intStatus & (1UL << EMMA2RH_SW_CASCADE)) {
 205                u32 swIntStatus;
 206                swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT)
 207                    & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
 208                for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
 209                        if (swIntStatus & bitmask) {
 210                                do_IRQ(EMMA2RH_SW_IRQ_BASE + i);
 211                                return;
 212                        }
 213                }
 214        }
 215        /* Skip S/W interrupt */
 216        intStatus &= ~(1UL << EMMA2RH_SW_CASCADE);
 217#endif
 218
 219        for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
 220                if (intStatus & bitmask) {
 221                        do_IRQ(EMMA2RH_IRQ_BASE + i);
 222                        return;
 223                }
 224        }
 225
 226        intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1) &
 227                    emma2rh_in32(EMMA2RH_BHIF_INT_EN_1);
 228
 229#ifdef EMMA2RH_GPIO_CASCADE
 230        if (intStatus & (1UL << (EMMA2RH_GPIO_CASCADE % 32))) {
 231                u32 gpioIntStatus;
 232                gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST)
 233                    & emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
 234                for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
 235                        if (gpioIntStatus & bitmask) {
 236                                do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i);
 237                                return;
 238                        }
 239                }
 240        }
 241        /* Skip GPIO interrupt */
 242        intStatus &= ~(1UL << (EMMA2RH_GPIO_CASCADE % 32));
 243#endif
 244
 245        for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) {
 246                if (intStatus & bitmask) {
 247                        do_IRQ(EMMA2RH_IRQ_BASE + i);
 248                        return;
 249                }
 250        }
 251
 252        intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2) &
 253                    emma2rh_in32(EMMA2RH_BHIF_INT_EN_2);
 254
 255        for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) {
 256                if (intStatus & bitmask) {
 257                        do_IRQ(EMMA2RH_IRQ_BASE + i);
 258                        return;
 259                }
 260        }
 261}
 262
 263void __init arch_init_irq(void)
 264{
 265        u32 reg;
 266
 267        /* by default, interrupts are disabled. */
 268        emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0);
 269        emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0);
 270        emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0);
 271        emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0);
 272        emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0);
 273        emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0);
 274        emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0);
 275
 276        clear_c0_status(0xff00);
 277        set_c0_status(0x0400);
 278
 279#define GPIO_PCI (0xf<<15)
 280        /* setup GPIO interrupt for PCI interface */
 281        /* direction input */
 282        reg = emma2rh_in32(EMMA2RH_GPIO_DIR);
 283        emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI);
 284        /* disable interrupt */
 285        reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
 286        emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI);
 287        /* level triggerd */
 288        reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE);
 289        emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI);
 290        reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A);
 291        emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI));
 292        /* interrupt clear */
 293        emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI);
 294
 295        /* init all controllers */
 296        emma2rh_irq_init();
 297        emma2rh_sw_irq_init();
 298        emma2rh_gpio_irq_init();
 299        mips_cpu_irq_init();
 300
 301        /* setup cascade interrupts */
 302        setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade);
 303        setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade);
 304        setup_irq(MIPS_CPU_IRQ_BASE + 2, &irq_cascade);
 305}
 306
 307asmlinkage void plat_irq_dispatch(void)
 308{
 309        unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
 310
 311        if (pending & STATUSF_IP7)
 312                do_IRQ(MIPS_CPU_IRQ_BASE + 7);
 313        else if (pending & STATUSF_IP2)
 314                emma2rh_irq_dispatch();
 315        else if (pending & STATUSF_IP1)
 316                do_IRQ(MIPS_CPU_IRQ_BASE + 1);
 317        else if (pending & STATUSF_IP0)
 318                do_IRQ(MIPS_CPU_IRQ_BASE + 0);
 319        else
 320                spurious_interrupt();
 321}
 322