PageRenderTime 23ms CodeModel.GetById 12ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/v850/kernel/v850e_intc.c

https://bitbucket.org/evzijst/gittest
C | 104 lines | 48 code | 13 blank | 43 comment | 4 complexity | a4edd0ca7afd26636773d9c52ea45e12 MD5 | raw file
  1/*
  2 * arch/v850/kernel/v850e_intc.c -- V850E interrupt controller (INTC)
  3 *
  4 *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  5 *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  6 *
  7 * This file is subject to the terms and conditions of the GNU General
  8 * Public License.  See the file COPYING in the main directory of this
  9 * archive for more details.
 10 *
 11 * Written by Miles Bader <miles@gnu.org>
 12 */
 13
 14#include <linux/kernel.h>
 15#include <linux/init.h>
 16#include <linux/irq.h>
 17
 18#include <asm/v850e_intc.h>
 19
 20static void irq_nop (unsigned irq) { }
 21
 22static unsigned v850e_intc_irq_startup (unsigned irq)
 23{
 24	v850e_intc_clear_pending_irq (irq);
 25	v850e_intc_enable_irq (irq);
 26	return 0;
 27}
 28
 29static void v850e_intc_end_irq (unsigned irq)
 30{
 31	unsigned long psw, temp;
 32
 33	/* Clear the highest-level bit in the In-service priority register
 34	   (ISPR), to allow this interrupt (or another of the same or
 35	   lesser priority) to happen again.
 36
 37	   The `reti' instruction normally does this automatically when the
 38	   PSW bits EP and NP are zero, but we can't always rely on reti
 39	   being used consistently to return after an interrupt (another
 40	   process can be scheduled, for instance, which can delay the
 41	   associated reti for a long time, or this process may be being
 42	   single-stepped, which uses the `dbret' instruction to return
 43	   from the kernel).
 44
 45	   We also set the PSW EP bit, which prevents reti from also
 46	   trying to modify the ISPR itself.  */
 47
 48	/* Get PSW and disable interrupts.  */
 49	asm volatile ("stsr psw, %0; di" : "=r" (psw));
 50	/* We don't want to do anything for NMIs (they don't use the ISPR).  */
 51	if (! (psw & 0xC0)) {
 52		/* Transition to `trap' state, so that an eventual real
 53		   reti instruction won't modify the ISPR.  */
 54		psw |= 0x40;
 55		/* Fake an interrupt return, which automatically clears the
 56		   appropriate bit in the ISPR.  */
 57		asm volatile ("mov hilo(1f), %0;"
 58			      "ldsr %0, eipc; ldsr %1, eipsw;"
 59			      "reti;"
 60			      "1:"
 61			      : "=&r" (temp) : "r" (psw));
 62	}
 63}
 64
 65/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
 66   INITS (which is terminated by an entry with the name field == 0).  */
 67void __init v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits,
 68				       struct hw_interrupt_type *hw_irq_types)
 69{
 70	struct v850e_intc_irq_init *init;
 71	for (init = inits; init->name; init++) {
 72		unsigned i;
 73		struct hw_interrupt_type *hwit = hw_irq_types++;
 74
 75		hwit->typename = init->name;
 76
 77		hwit->startup  = v850e_intc_irq_startup;
 78		hwit->shutdown = v850e_intc_disable_irq;
 79		hwit->enable   = v850e_intc_enable_irq;
 80		hwit->disable  = v850e_intc_disable_irq;
 81		hwit->ack      = irq_nop;
 82		hwit->end      = v850e_intc_end_irq;
 83		
 84		/* Initialize kernel IRQ infrastructure for this interrupt.  */
 85		init_irq_handlers(init->base, init->num, init->interval, hwit);
 86
 87		/* Set the interrupt priorities.  */
 88		for (i = 0; i < init->num; i++) {
 89			unsigned irq = init->base + i * init->interval;
 90
 91			/* If the interrupt is currently enabled (all
 92			   interrupts are initially disabled), then
 93			   assume whoever enabled it has set things up
 94			   properly, and avoid messing with it.  */
 95			if (! v850e_intc_irq_enabled (irq))
 96				/* This write also (1) disables the
 97				   interrupt, and (2) clears any pending
 98				   interrupts.  */
 99				V850E_INTC_IC (irq)
100					= (V850E_INTC_IC_PR (init->priority)
101					   | V850E_INTC_IC_MK);
102		}
103	}
104}