1/* $NetBSD: omap_intr.h,v 1.5 2008/11/21 17:13:07 matt Exp $ */ 2 3/* 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain this list of conditions 8 * and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce this list of conditions 10 * and the following disclaimer in the documentation and/or other materials 11 * provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY 16 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 19 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 21 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25/* 26 * This file used pxa2x0_intr.h as a template, but now bears little semblance 27 * to it. In its new form, it should not be included directly. Rather, it 28 * should only be included from an include file that is specific to a 29 * particular OMAP (e.g. omap5912_intr.h). That file will define the 30 * information that varies from OMAP to OMAP and then includes this file to 31 * provide the OMAP generic information. As more OMAP ports are done, more 32 * information may need to move from this file out into the particular OMAP 33 * header files. 34 */ 35 36#ifndef _ARM_OMAP_OMAP_INTR_H_ 37#define _ARM_OMAP_OMAP_INTR_H_ 38 39#define ARM_IRQ_HANDLER _C_LABEL(omap_irq_handler) 40 41#ifndef _LOCORE 42 43#include <arm/cpu.h> 44#include <arm/armreg.h> 45#include <arm/cpufunc.h> 46 47#define OMAP_IRQ_MIN 0 48#define OMAP_NIRQ (OMAP_INT_L1_NIRQ + OMAP_INT_L2_NIRQ) 49#define OMAP_BANK_WIDTH (32) 50#if (OMAP_NIRQ & (OMAP_BANK_WIDTH - 1)) 51#error OMAP_NIRQ must be an even multiple of OMAP_BANK_WIDTH 52#endif 53#define OMAP_NBANKS (OMAP_NIRQ / OMAP_BANK_WIDTH) 54 55/* Offsets within the OMAP interrupt controllers */ 56#define OMAP_INTC_SIR_IRQ 0x10 /* Interrupt source register (IRQ) */ 57#define OMAP_INTC_SIR_FIQ 0x14 /* Interrupt source register (FIQ) */ 58/* These registers differ in meaning between L1 and L2 controllers */ 59#define OMAP_INTL1_CONTROL 0x18 /* Interrupt control register */ 60#define OMAP_INTL1_CONTROL_NEW_FIQ_AGR (1<<1) 61#define OMAP_INTL1_CONTROL_NEW_IRQ_AGR (1<<0) 62#define OMAP_INTL1_GMR 0xA0 /* Global mask interrupt register */ 63#define OMAP_INTL1_GMR_GLOBAL_MASK (1<<0) 64#define OMAP_INTL2_CONTROL 0x18 /* Interrupt control register */ 65#define OMAP_INTL2_CONTROL_GLOBAL_MASK (1<<2) 66#define OMAP_INTL2_CONTROL_NEW_FIQ_AGR (1<<1) 67#define OMAP_INTL2_CONTROL_NEW_IRQ_AGR (1<<0) 68#define OMAP_INTL2_STATUS 0xA0 /* Status register */ 69#define OMAP_INTL2_STATUS_RESET_DONE (1<<0) 70#define OMAP_INTL2_OCP_CFG 0xA4 /* OCP configuration register */ 71#define OMAP_INTL2_OCP_CFG_FORCE_WAKEUP (0<<3) 72#define OMAP_INTL2_OCP_CFG_SMART_IDLE (2<<3) 73#define OMAP_INTL2_OCP_CFG_SOFTRESET (1<<1) 74#define OMAP_INTL2_OCP_CFG_AUTOIDLE (1<<0) 75#define OMAP_INTL2_INTH_REV 0xA8 /* Interrupt controller revision ID */ 76#define OMAP_INTL2_INTH_REV_MAJOR(r) (((r)&0xF0)>>4) 77#define OMAP_INTL2_INTH_REV_MINOR(r) ((r)&0x0F) 78#define OMAP_INTL2_BANK_OFF 0x100 /* Offset between each bank. */ 79 80 81/* Offsets within the banks of the OMAP interrupt controllers */ 82#define OMAP_INTB_ITR 0x00 /* Interrupt register */ 83#define OMAP_INTB_MIR 0x04 /* Interrupt mask register */ 84#define OMAP_INTB_ILR_BASE 0x1C /* Interrupt priority level register */ 85#define OMAP_INTB_ILR_PRIO_SHIFT 2 86#define OMAP_INTB_ILR_PRIO_LOWEST 31 /* L2's really 127 */ 87#define OMAP_INTB_ILR_PRIO_HIGHEST 0 88#define OMAP_INTB_ILR_EDGE (0<<1) 89#define OMAP_INTB_ILR_LEVEL (1<<1) 90#define OMAP_INTB_ILR_IRQ (0<<0) 91#define OMAP_INTB_ILR_FIQ (1<<0) 92#define OMAP_INTB_SISR 0x9C /* Software interrupt set register */ 93 94/* Array of structures that allow us to get per interrupt constants. */ 95typedef enum { 96 /* 0 in this field marks a reserved interrupt that should not be used. */ 97 INVALID = 0, 98 TRIG_LEVEL, 99 TRIG_EDGE, 100 TRIG_LEVEL_OR_EDGE 101} omap_intr_trig_t; 102typedef struct { 103 omap_intr_trig_t trig; 104 vaddr_t bank_base; 105 int bank_num; 106 vaddr_t ILR; 107 uint32_t mask; 108} omap_intr_info_t; 109extern const omap_intr_info_t omap_intr_info[OMAP_NIRQ]; 110 111/* Array of pointers to each bank's base. */ 112extern vaddr_t omap_intr_bank_bases[OMAP_NBANKS]; 113 114/* Array of arrays to give us the per bank masks for each level. */ 115extern uint32_t omap_spl_masks[NIPL][OMAP_NBANKS]; 116/* Array of globally-off masks while interrupts processed. */ 117extern uint32_t omap_global_masks[OMAP_NBANKS]; 118 119/* 120 * Direct access is being done because 1) it's faster and 2) the interrupt 121 * controller code is still very tied to the OMAP so we don't really have 122 * the concept of going through a bus at an address specified in the config. 123 */ 124#define read_icu(base,offset) (*(volatile uint32_t *)((base)+(offset))) 125#define write_icu(base,offset,value) \ 126 (*(volatile uint32_t *)((base)+(offset))=(value)) 127 128static inline void 129omap_splx(int new) 130{ 131 vaddr_t *bases = &omap_intr_bank_bases[0]; 132 uint32_t *masks = &omap_spl_masks[new][0]; 133 int psw = disable_interrupts(I32_bit); 134 135 set_curcpl(new); 136 137#if OMAP_NBANKS != 5 138#error Revisit loop unrolling in omap_splx() 139#endif 140 write_icu(bases[0], OMAP_INTB_MIR, masks[0] | omap_global_masks[0]); 141 write_icu(bases[1], OMAP_INTB_MIR, masks[1] | omap_global_masks[1]); 142 write_icu(bases[2], OMAP_INTB_MIR, masks[2] | omap_global_masks[2]); 143 write_icu(bases[3], OMAP_INTB_MIR, masks[3] | omap_global_masks[3]); 144 write_icu(bases[4], OMAP_INTB_MIR, masks[4] | omap_global_masks[4]); 145#ifdef __HAVE_FAST_SOFTINTS 146 cpu_dosoftintrs(); 147#endif 148 restore_interrupts(psw); 149} 150 151static inline int 152omap_splraise(int ipl) 153{ 154 const int old = curcpl(); 155 if (ipl > old) 156 omap_splx(ipl); 157 return (old); 158} 159 160static inline int 161omap_spllower(int ipl) 162{ 163 const int old = curcpl(); 164 omap_splx(ipl); 165 return(old); 166} 167 168int _splraise(int); 169int _spllower(int); 170void splx(int); 171#ifdef __HAVE_FAST_SOFTINTS 172void _setsoftintr(int); 173#endif 174 175#if !defined(EVBARM_SPL_NOINLINE) 176#define splx(new) omap_splx(new) 177#define _spllower(ipl) omap_spllower(ipl) 178#define _splraise(ipl) omap_splraise(ipl) 179#ifdef __HAVE_FAST_SOFTINTS 180#define _setsoftintr(si) omap_setsoftintr(si) 181#endif 182#endif /* !EVBARM_SPL_NOINTR */ 183 184void omap_irq_handler(void *); 185void *omap_intr_establish(int, int, const char *, int (*)(void *), void *); 186void omap_intr_disestablish(void *); 187/* XXX MARTY -- This is a hack to work around the circular dependency 188 * between sys/device.h and omap_intr.h It should be removed when 189 * the circular dependency is fixed and the declaration repaired. 190 */ 191struct cfdata; 192int omapintc_match(device_t, struct cfdata *, void *); 193void omapintc_attach(device_t, device_t, void *); 194 195#endif /* ! _LOCORE */ 196 197#endif /* _ARM_OMAP_OMAP_INTR_H_ */ 198