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