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