linux/arch/mips/pmc-sierra/yosemite/irq.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2003 PMC-Sierra Inc.
   3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
   4 *
   5 * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
   6 *
   7 *  This program is free software; you can redistribute  it and/or modify it
   8 *  under  the terms of  the GNU General  Public License as published by the
   9 *  Free Software Foundation;  either version 2 of the  License, or (at your
  10 *  option) any later version.
  11 *
  12 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  13 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  14 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  15 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  16 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  17 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  18 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  19 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  20 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  21 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22 *
  23 *  You should have received a copy of the  GNU General Public License along
  24 *  with this program; if not, write  to the Free Software Foundation, Inc.,
  25 *  675 Mass Ave, Cambridge, MA 02139, USA.
  26 *
  27 * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
  28 */
  29#include <linux/errno.h>
  30#include <linux/init.h>
  31#include <linux/kernel_stat.h>
  32#include <linux/module.h>
  33#include <linux/signal.h>
  34#include <linux/sched.h>
  35#include <linux/types.h>
  36#include <linux/interrupt.h>
  37#include <linux/ioport.h>
  38#include <linux/irq.h>
  39#include <linux/timex.h>
  40#include <linux/random.h>
  41#include <linux/bitops.h>
  42#include <asm/bootinfo.h>
  43#include <asm/io.h>
  44#include <asm/irq.h>
  45#include <asm/irq_cpu.h>
  46#include <asm/mipsregs.h>
  47#include <asm/system.h>
  48#include <asm/titan_dep.h>
  49
  50/* Hypertransport specific */
  51#define IRQ_ACK_BITS            0x00000000      /* Ack bits */
  52
  53#define HYPERTRANSPORT_INTA     0x78            /* INTA# */
  54#define HYPERTRANSPORT_INTB     0x79            /* INTB# */
  55#define HYPERTRANSPORT_INTC     0x7a            /* INTC# */
  56#define HYPERTRANSPORT_INTD     0x7b            /* INTD# */
  57
  58extern void titan_mailbox_irq(void);
  59
  60#ifdef CONFIG_HYPERTRANSPORT
  61/*
  62 * Handle hypertransport & SMP interrupts. The interrupt lines are scarce.
  63 * For interprocessor interrupts, the best thing to do is to use the INTMSG
  64 * register. We use the same external interrupt line, i.e. INTB3 and monitor
  65 * another status bit
  66 */
  67static void ll_ht_smp_irq_handler(int irq)
  68{
  69        u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
  70
  71        /* Ack all the bits that correspond to the interrupt sources */
  72        if (status != 0)
  73                OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS);
  74
  75        status = OCD_READ(RM9000x2_OCD_INTP1STATUS4);
  76        if (status != 0)
  77                OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS);
  78
  79#ifdef CONFIG_HT_LEVEL_TRIGGER
  80        /*
  81         * Level Trigger Mode only. Send the HT EOI message back to the source.
  82         */
  83        switch (status) {
  84        case 0x1000000:
  85                OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
  86                break;
  87        case 0x2000000:
  88                OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
  89                break;
  90        case 0x4000000:
  91                OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
  92                break;
  93        case 0x8000000:
  94                OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
  95                break;
  96        case 0x0000001:
  97                /* PLX */
  98                OCD_WRITE(RM9000x2_OCD_HTEOI, 0x20);
  99                OCD_WRITE(IRQ_CLEAR_REG, IRQ_ACK_BITS);
 100                break;
 101        case 0xf000000:
 102                OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
 103                OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
 104                OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
 105                OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
 106                break;
 107        }
 108#endif /* CONFIG_HT_LEVEL_TRIGGER */
 109
 110        do_IRQ(irq);
 111}
 112#endif
 113
 114asmlinkage void plat_irq_dispatch(void)
 115{
 116        unsigned int cause = read_c0_cause();
 117        unsigned int status = read_c0_status();
 118        unsigned int pending = cause & status;
 119
 120        if (pending & STATUSF_IP7) {
 121                do_IRQ(7);
 122        } else if (pending & STATUSF_IP2) {
 123#ifdef CONFIG_HYPERTRANSPORT
 124                ll_ht_smp_irq_handler(2);
 125#else
 126                do_IRQ(2);
 127#endif
 128        } else if (pending & STATUSF_IP3) {
 129                do_IRQ(3);
 130        } else if (pending & STATUSF_IP4) {
 131                do_IRQ(4);
 132        } else if (pending & STATUSF_IP5) {
 133#ifdef CONFIG_SMP
 134                titan_mailbox_irq();
 135#else
 136                do_IRQ(5);
 137#endif
 138        } else if (pending & STATUSF_IP6) {
 139                do_IRQ(4);
 140        }
 141}
 142
 143/*
 144 * Initialize the next level interrupt handler
 145 */
 146void __init arch_init_irq(void)
 147{
 148        clear_c0_status(ST0_IM);
 149
 150        mips_cpu_irq_init();
 151        rm7k_cpu_irq_init();
 152        rm9k_cpu_irq_init();
 153}
 154