| /* |
| * 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__ */ |