/*1* Copyright 2001 MontaVista Software Inc.2* Author: Jun Sun, [email protected] or [email protected]3*4* Copyright (C) 2001 Ralf Baechle5* Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.6* Author: Maciej W. Rozycki <[email protected]>7*8* This file define the irq handler for MIPS CPU interrupts.9*10* This program is free software; you can redistribute it and/or modify it11* under the terms of the GNU General Public License as published by the12* Free Software Foundation; either version 2 of the License, or (at your13* option) any later version.14*/1516/*17* Almost all MIPS CPUs define 8 interrupt sources. They are typically18* level triggered (i.e., cannot be cleared from CPU; must be cleared from19* device). The first two are software interrupts which we don't really20* use or support. The last one is usually the CPU timer interrupt if21* counter register is present or, for CPUs with an external FPU, by22* convention it's the FPU exception interrupt.23*24* Don't even think about using this on SMP. You have been warned.25*26* This file exports one global function:27* void mips_cpu_irq_init(void);28*/29#include <linux/init.h>30#include <linux/interrupt.h>31#include <linux/kernel.h>32#include <linux/irq.h>3334#include <asm/irq_cpu.h>35#include <asm/mipsregs.h>36#include <asm/mipsmtregs.h>37#include <asm/system.h>3839static inline void unmask_mips_irq(struct irq_data *d)40{41set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));42irq_enable_hazard();43}4445static inline void mask_mips_irq(struct irq_data *d)46{47clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));48irq_disable_hazard();49}5051static struct irq_chip mips_cpu_irq_controller = {52.name = "MIPS",53.irq_ack = mask_mips_irq,54.irq_mask = mask_mips_irq,55.irq_mask_ack = mask_mips_irq,56.irq_unmask = unmask_mips_irq,57.irq_eoi = unmask_mips_irq,58};5960/*61* Basically the same as above but taking care of all the MT stuff62*/6364static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)65{66unsigned int vpflags = dvpe();6768clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));69evpe(vpflags);70unmask_mips_irq(d);71return 0;72}7374/*75* While we ack the interrupt interrupts are disabled and thus we don't need76* to deal with concurrency issues. Same for mips_cpu_irq_end.77*/78static void mips_mt_cpu_irq_ack(struct irq_data *d)79{80unsigned int vpflags = dvpe();81clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));82evpe(vpflags);83mask_mips_irq(d);84}8586static struct irq_chip mips_mt_cpu_irq_controller = {87.name = "MIPS",88.irq_startup = mips_mt_cpu_irq_startup,89.irq_ack = mips_mt_cpu_irq_ack,90.irq_mask = mask_mips_irq,91.irq_mask_ack = mips_mt_cpu_irq_ack,92.irq_unmask = unmask_mips_irq,93.irq_eoi = unmask_mips_irq,94};9596void __init mips_cpu_irq_init(void)97{98int irq_base = MIPS_CPU_IRQ_BASE;99int i;100101/* Mask interrupts. */102clear_c0_status(ST0_IM);103clear_c0_cause(CAUSEF_IP);104105/*106* Only MT is using the software interrupts currently, so we just107* leave them uninitialized for other processors.108*/109if (cpu_has_mipsmt)110for (i = irq_base; i < irq_base + 2; i++)111irq_set_chip_and_handler(i, &mips_mt_cpu_irq_controller,112handle_percpu_irq);113114for (i = irq_base + 2; i < irq_base + 8; i++)115irq_set_chip_and_handler(i, &mips_cpu_irq_controller,116handle_percpu_irq);117}118119120