ia64/linux-2.6.18-xen.hg

annotate arch/v850/kernel/v850e_intc.c @ 854:950b9eb27661

usbback: fix urb interval value for interrupt urbs.

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