Commit 050e6ae5 authored by Miles Bader's avatar Miles Bader Committed by Linus Torvalds

[PATCH] On the v850/nb85e, acknowledge interrupts immediately after handling them

Previously, it was done automatically by the `reti' isntruction upon
returning from the kernel, but that doesn't do the correct thing in
various cases, for instance if there's a context switch, or a softirq.
parent 47ebae08
/*
* arch/v850/kernel/nb85e_intc.c -- NB85E cpu core interrupt controller (INTC)
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
* Copyright (C) 2001,02,03 NEC Electronics Corporation
* Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
......@@ -26,6 +26,42 @@ static unsigned nb85e_intc_irq_startup (unsigned irq)
return 0;
}
static void nb85e_intc_end_irq (unsigned irq)
{
unsigned long psw, temp;
/* Clear the highest-level bit in the In-service priority register
(ISPR), to allow this interrupt (or another of the same or
lesser priority) to happen again.
The `reti' instruction normally does this automatically when the
PSW bits EP and NP are zero, but we can't always rely on reti
being used consistently to return after an interrupt (another
process can be scheduled, for instance, which can delay the
associated reti for a long time, or this process may be being
single-stepped, which uses the `dbret' instruction to return
from the kernel).
We also set the PSW EP bit, which prevents reti from also
trying to modify the ISPR itself. */
/* Get PSW and disable interrupts. */
asm volatile ("stsr psw, %0; di" : "=r" (psw));
/* We don't want to do anything for NMIs (they don't use the ISPR). */
if (! (psw & 0xC0)) {
/* Transition to `trap' state, so that an eventual real
reti instruction won't modify the ISPR. */
psw |= 0x40;
/* Fake an interrupt return, which automatically clears the
appropriate bit in the ISPR. */
asm volatile ("mov hilo(1f), %0;"
"ldsr %0, eipc; ldsr %1, eipsw;"
"reti;"
"1:"
: "=&r" (temp) : "r" (psw));
}
}
/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
INITS (which is terminated by an entry with the name field == 0). */
void __init nb85e_intc_init_irq_types (struct nb85e_intc_irq_init *inits,
......@@ -43,7 +79,7 @@ void __init nb85e_intc_init_irq_types (struct nb85e_intc_irq_init *inits,
hwit->enable = nb85e_intc_enable_irq;
hwit->disable = nb85e_intc_disable_irq;
hwit->ack = irq_nop;
hwit->end = irq_nop;
hwit->end = nb85e_intc_end_irq;
/* Initialize kernel IRQ infrastructure for this interrupt. */
init_irq_handlers(init->base, init->num, init->interval, hwit);
......
/*
* include/asm-v850/nb85e_intc.h -- NB85E cpu core interrupt controller (INTC)
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
* Copyright (C) 2001,02,03 NEC Electronics Corporation
* Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
......@@ -26,7 +26,7 @@
address. */
#define NB85E_INTC_IC_BASE_ADDR 0xFFFFF110
#define NB85E_INTC_IC_ADDR(irq) (NB85E_INTC_IC_BASE_ADDR + ((irq) << 1))
#define NB85E_INTC_IC(irq) (*(char *)NB85E_INTC_IC_ADDR(irq))
#define NB85E_INTC_IC(irq) (*(volatile u8 *)NB85E_INTC_IC_ADDR(irq))
/* Encode priority PR for storing in an interrupt control register. */
#define NB85E_INTC_IC_PR(pr) (pr)
/* Interrupt disable bit in an interrupt control register. */
......@@ -36,6 +36,13 @@
#define NB85E_INTC_IC_IF_BIT 7
#define NB85E_INTC_IC_IF (1 << NB85E_INTC_IC_IF_BIT)
/* The ISPR (In-service priority register) contains one bit for each interrupt
priority level, which is set to one when that level is currently being
serviced (and thus blocking any interrupts of equal or lesser level). */
#define NB85E_INTC_ISPR_ADDR 0xFFFFF1FA
#define NB85E_INTC_ISPR (*(volatile u8 *)NB85E_INTC_ISPR_ADDR)
#ifndef __ASSEMBLY__
/* Enable interrupt handling for interrupt IRQ. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment