| /* | |
| * include/asm-v850/v850e_intc.h -- V850E CPU interrupt controller (INTC) | |
| * | |
| * 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 | |
| * archive for more details. | |
| * | |
| * Written by Miles Bader <miles@gnu.org> | |
| */ | |
| #ifndef __V850_V850E_INTC_H__ | |
| #define __V850_V850E_INTC_H__ | |
| /* There are 4 16-bit `Interrupt Mask Registers' located contiguously | |
| starting from this base. Each interrupt uses a single bit to | |
| indicated enabled/disabled status. */ | |
| #define V850E_INTC_IMR_BASE_ADDR 0xFFFFF100 | |
| #define V850E_INTC_IMR_ADDR(irq) (V850E_INTC_IMR_BASE_ADDR + ((irq) >> 3)) | |
| #define V850E_INTC_IMR_BIT(irq) ((irq) & 0x7) | |
| /* Each maskable interrupt has a single-byte control register at this | |
| address. */ | |
| #define V850E_INTC_IC_BASE_ADDR 0xFFFFF110 | |
| #define V850E_INTC_IC_ADDR(irq) (V850E_INTC_IC_BASE_ADDR + ((irq) << 1)) | |
| #define V850E_INTC_IC(irq) (*(volatile u8 *)V850E_INTC_IC_ADDR(irq)) | |
| /* Encode priority PR for storing in an interrupt control register. */ | |
| #define V850E_INTC_IC_PR(pr) (pr) | |
| /* Interrupt disable bit in an interrupt control register. */ | |
| #define V850E_INTC_IC_MK_BIT 6 | |
| #define V850E_INTC_IC_MK (1 << V850E_INTC_IC_MK_BIT) | |
| /* Interrupt pending flag in an interrupt control register. */ | |
| #define V850E_INTC_IC_IF_BIT 7 | |
| #define V850E_INTC_IC_IF (1 << V850E_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 V850E_INTC_ISPR_ADDR 0xFFFFF1FA | |
| #define V850E_INTC_ISPR (*(volatile u8 *)V850E_INTC_ISPR_ADDR) | |
| #ifndef __ASSEMBLY__ | |
| /* Enable interrupt handling for interrupt IRQ. */ | |
| static inline void v850e_intc_enable_irq (unsigned irq) | |
| { | |
| __asm__ __volatile__ ("clr1 %0, [%1]" | |
| :: "r" (V850E_INTC_IMR_BIT (irq)), | |
| "r" (V850E_INTC_IMR_ADDR (irq)) | |
| : "memory"); | |
| } | |
| /* Disable interrupt handling for interrupt IRQ. Note that any | |
| interrupts received while disabled will be delivered once the | |
| interrupt is enabled again, unless they are explicitly cleared using | |
| `v850e_intc_clear_pending_irq'. */ | |
| static inline void v850e_intc_disable_irq (unsigned irq) | |
| { | |
| __asm__ __volatile__ ("set1 %0, [%1]" | |
| :: "r" (V850E_INTC_IMR_BIT (irq)), | |
| "r" (V850E_INTC_IMR_ADDR (irq)) | |
| : "memory"); | |
| } | |
| /* Return true if interrupt handling for interrupt IRQ is enabled. */ | |
| static inline int v850e_intc_irq_enabled (unsigned irq) | |
| { | |
| int rval; | |
| __asm__ __volatile__ ("tst1 %1, [%2]; setf z, %0" | |
| : "=r" (rval) | |
| : "r" (V850E_INTC_IMR_BIT (irq)), | |
| "r" (V850E_INTC_IMR_ADDR (irq))); | |
| return rval; | |
| } | |
| /* Disable irqs from 0 until LIMIT. LIMIT must be a multiple of 8. */ | |
| static inline void _v850e_intc_disable_irqs (unsigned limit) | |
| { | |
| unsigned long addr; | |
| for (addr = V850E_INTC_IMR_BASE_ADDR; limit >= 8; addr++, limit -= 8) | |
| *(char *)addr = 0xFF; | |
| } | |
| /* Disable all irqs. This is purposely a macro, because NUM_MACH_IRQS | |
| will be only be defined later. */ | |
| #define v850e_intc_disable_irqs() _v850e_intc_disable_irqs (NUM_MACH_IRQS) | |
| /* Clear any pending interrupts for IRQ. */ | |
| static inline void v850e_intc_clear_pending_irq (unsigned irq) | |
| { | |
| __asm__ __volatile__ ("clr1 %0, 0[%1]" | |
| :: "i" (V850E_INTC_IC_IF_BIT), | |
| "r" (V850E_INTC_IC_ADDR (irq)) | |
| : "memory"); | |
| } | |
| /* Return true if interrupt IRQ is pending (but disabled). */ | |
| static inline int v850e_intc_irq_pending (unsigned irq) | |
| { | |
| int rval; | |
| __asm__ __volatile__ ("tst1 %1, 0[%2]; setf nz, %0" | |
| : "=r" (rval) | |
| : "i" (V850E_INTC_IC_IF_BIT), | |
| "r" (V850E_INTC_IC_ADDR (irq))); | |
| return rval; | |
| } | |
| struct v850e_intc_irq_init { | |
| const char *name; /* name of interrupt type */ | |
| /* Range of kernel irq numbers for this type: | |
| BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM */ | |
| unsigned base, num, interval; | |
| unsigned priority; /* interrupt priority to assign */ | |
| }; | |
| struct hw_interrupt_type; /* fwd decl */ | |
| /* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array | |
| INITS (which is terminated by an entry with the name field == 0). */ | |
| extern void v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits, | |
| struct hw_interrupt_type *hw_irq_types); | |
| #endif /* !__ASSEMBLY__ */ | |
| #endif /* __V850_V850E_INTC_H__ */ |