linux/arch/mips/txx9/rbtx4939/irq.c
<<
>>
Prefs
   1/*
   2 * Toshiba RBTX4939 interrupt routines
   3 * Based on linux/arch/mips/txx9/rbtx4938/irq.c,
   4 *          and RBTX49xx patch from CELF patch archive.
   5 *
   6 * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation
   7 * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
   8 * terms of the GNU General Public License version 2. This program is
   9 * licensed "as is" without any warranty of any kind, whether express
  10 * or implied.
  11 */
  12#include <linux/init.h>
  13#include <linux/interrupt.h>
  14#include <linux/irq.h>
  15#include <asm/mipsregs.h>
  16#include <asm/txx9/rbtx4939.h>
  17
  18/*
  19 * RBTX4939 IOC controller definition
  20 */
  21
  22static void rbtx4939_ioc_irq_unmask(struct irq_data *d)
  23{
  24        int ioc_nr = d->irq - RBTX4939_IRQ_IOC;
  25
  26        writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr);
  27}
  28
  29static void rbtx4939_ioc_irq_mask(struct irq_data *d)
  30{
  31        int ioc_nr = d->irq - RBTX4939_IRQ_IOC;
  32
  33        writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr);
  34        mmiowb();
  35}
  36
  37static struct irq_chip rbtx4939_ioc_irq_chip = {
  38        .name           = "IOC",
  39        .irq_mask       = rbtx4939_ioc_irq_mask,
  40        .irq_unmask     = rbtx4939_ioc_irq_unmask,
  41};
  42
  43
  44static inline int rbtx4939_ioc_irqroute(void)
  45{
  46        unsigned char istat = readb(rbtx4939_ifac2_addr);
  47
  48        if (unlikely(istat == 0))
  49                return -1;
  50        return RBTX4939_IRQ_IOC + __fls8(istat);
  51}
  52
  53static int rbtx4939_irq_dispatch(int pending)
  54{
  55        int irq;
  56
  57        if (pending & CAUSEF_IP7)
  58                return MIPS_CPU_IRQ_BASE + 7;
  59        irq = tx4939_irq();
  60        if (likely(irq >= 0)) {
  61                /* redirect IOC interrupts */
  62                switch (irq) {
  63                case RBTX4939_IRQ_IOCINT:
  64                        irq = rbtx4939_ioc_irqroute();
  65                        break;
  66                }
  67        } else if (pending & CAUSEF_IP0)
  68                irq = MIPS_CPU_IRQ_BASE + 0;
  69        else if (pending & CAUSEF_IP1)
  70                irq = MIPS_CPU_IRQ_BASE + 1;
  71        else
  72                irq = -1;
  73        return irq;
  74}
  75
  76void __init rbtx4939_irq_setup(void)
  77{
  78        int i;
  79
  80        /* mask all IOC interrupts */
  81        writeb(0, rbtx4939_ien_addr);
  82
  83        /* clear SoftInt interrupts */
  84        writeb(0, rbtx4939_softint_addr);
  85
  86        txx9_irq_dispatch = rbtx4939_irq_dispatch;
  87
  88        tx4939_irq_init();
  89        for (i = RBTX4939_IRQ_IOC;
  90             i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++)
  91                irq_set_chip_and_handler(i, &rbtx4939_ioc_irq_chip,
  92                                         handle_level_irq);
  93
  94        irq_set_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq);
  95}
  96