diff options
Diffstat (limited to 'include/asm-v850/v850e_intc.h')
-rw-r--r-- | include/asm-v850/v850e_intc.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/include/asm-v850/v850e_intc.h b/include/asm-v850/v850e_intc.h new file mode 100644 index 000000000000..6fdf95708317 --- /dev/null +++ b/include/asm-v850/v850e_intc.h @@ -0,0 +1,133 @@ +/* + * 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__ */ |