Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / powerpc / marvell / marvell_intr.h
blob3a84a4fd4517d23ec996b7a7de9a7dc296a1f19c
1 /* $NetBSD: marvell_intr.h,v 1.15 2008/04/28 20:23:32 martin Exp $ */
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #ifndef _MVPPPC_INTR_H_
33 #define _MVPPPC_INTR_H_
35 #include <powerpc/psl.h>
36 #include <powerpc/frame.h>
39 * Interrupt Priority Levels
41 #define IPL_NONE 0 /* nothing */
42 #define IPL_SOFTCLOCK 1 /* timeouts */
43 #define IPL_SOFTBIO 2 /* block I/O */
44 #define IPL_SOFTNET 3 /* protocol stacks */
45 #define IPL_SOFTSERIAL 4 /* serial */
46 #define IPL_VM 12 /* memory allocation */
47 #define IPL_SCHED 14 /* clock */
48 #define IPL_HIGH 15 /* everything */
49 #define NIPL 16
50 #define IPL_PRIMASK 0xf
51 #define IPL_EE 0x10 /* enable external interrupts on splx */
53 /* Interrupt sharing types. */
54 #define IST_NONE 0 /* none */
55 #define IST_PULSE 1 /* pulsed */
56 #define IST_EDGE 2 /* edge-triggered */
57 #define IST_LEVEL 3 /* level-triggered */
58 #define IST_SOFT 4 /* software-triggered */
59 #define IST_CLOCK 5 /* exclusive for clock */
60 #define NIST 6
62 #if !defined(_LOCORE) && defined(_KERNEL)
64 #define CLKF_BASEPRI(frame) ((frame)->pri == IPL_NONE)
67 * we support 128 IRQs:
68 * 96 (ICU_LEN) hard interrupt IRQs:
69 * - 64 Main Cause IRQs,
70 * - 32 GPP IRQs,
71 * and 32 softint IRQs
73 #define ICU_LEN 96 /* number of HW IRQs */
74 #define IRQ_GPP_BASE 64 /* base of GPP IRQs */
75 #define IRQ_GPP_SUM (32+24) /* GPP[7..0] interrupt */ /* XXX */
76 #define NIRQ 128 /* total # of HW IRQs */
78 #define IMASK_ICU_LO 0
79 #define IMASK_ICU_HI 1
80 #define IMASK_ICU_GPP 2
81 #define IMASK_SOFTINT 3
82 #define IMASK_WORDSHIFT 5 /* log2(32) */
83 #define IMASK_BITMASK ~((~0) << IMASK_WORDSHIFT)
85 #define IRQ_IS_GPP(irq) ((irq >= IRQ_GPP_BASE) && (irq < ICU_LEN))
88 * interrupt mask bit vector
90 typedef struct {
91 u_int32_t bits[4];
92 } imask_t __attribute__ ((aligned(16)));
94 static inline void imask_zero(imask_t *);
95 static inline void imask_zero_v(volatile imask_t *);
96 static inline void imask_dup_v(imask_t *, const volatile imask_t *);
97 static inline void imask_and(imask_t *, const imask_t *);
98 static inline void imask_andnot_v(volatile imask_t *, const imask_t *);
99 static inline void imask_andnot_icu_vv(volatile imask_t *, const volatile imask_t *);
100 static inline int imask_empty(const imask_t *);
101 static inline void imask_orbit(imask_t *, int);
102 static inline void imask_orbit_v(volatile imask_t *, int);
103 static inline void imask_clrbit(imask_t *, int);
104 static inline void imask_clrbit_v(volatile imask_t *, int);
105 static inline u_int32_t imask_andbit_v(const volatile imask_t *, int);
106 static inline int imask_test_v(const volatile imask_t *, const imask_t *);
108 static inline void
109 imask_zero(imask_t *idp)
111 idp->bits[IMASK_ICU_LO] = 0;
112 idp->bits[IMASK_ICU_HI] = 0;
113 idp->bits[IMASK_ICU_GPP] = 0;
114 idp->bits[IMASK_SOFTINT] = 0;
117 static inline void
118 imask_zero_v(volatile imask_t *idp)
120 idp->bits[IMASK_ICU_LO] = 0;
121 idp->bits[IMASK_ICU_HI] = 0;
122 idp->bits[IMASK_ICU_GPP] = 0;
123 idp->bits[IMASK_SOFTINT] = 0;
126 static inline void
127 imask_dup_v(imask_t *idp, const volatile imask_t *isp)
129 *idp = *isp;
132 static inline void
133 imask_and(imask_t *idp, const imask_t *isp)
135 idp->bits[IMASK_ICU_LO] &= isp->bits[IMASK_ICU_LO];
136 idp->bits[IMASK_ICU_HI] &= isp->bits[IMASK_ICU_HI];
137 idp->bits[IMASK_ICU_GPP] &= isp->bits[IMASK_ICU_GPP];
138 idp->bits[IMASK_SOFTINT] &= isp->bits[IMASK_SOFTINT];
141 static inline void
142 imask_andnot_v(volatile imask_t *idp, const imask_t *isp)
144 idp->bits[IMASK_ICU_LO] &= ~isp->bits[IMASK_ICU_LO];
145 idp->bits[IMASK_ICU_HI] &= ~isp->bits[IMASK_ICU_HI];
146 idp->bits[IMASK_ICU_GPP] &= ~isp->bits[IMASK_ICU_GPP];
147 idp->bits[IMASK_SOFTINT] &= ~isp->bits[IMASK_SOFTINT];
150 static inline void
151 imask_andnot_icu_vv(volatile imask_t *idp, const volatile imask_t *isp)
153 idp->bits[IMASK_ICU_LO] &= ~isp->bits[IMASK_ICU_LO];
154 idp->bits[IMASK_ICU_HI] &= ~isp->bits[IMASK_ICU_HI];
155 idp->bits[IMASK_ICU_GPP] &= ~isp->bits[IMASK_ICU_GPP];
158 static inline int
159 imask_empty(const imask_t *isp)
161 return (! (isp->bits[IMASK_ICU_LO] | isp->bits[IMASK_ICU_HI] |
162 isp->bits[IMASK_ICU_GPP]| isp->bits[IMASK_SOFTINT]));
165 static inline void
166 imask_orbit(imask_t *idp, int bitno)
168 idp->bits[bitno>>IMASK_WORDSHIFT] |= (1 << (bitno&IMASK_BITMASK));
171 static inline void
172 imask_orbit_v(volatile imask_t *idp, int bitno)
174 idp->bits[bitno>>IMASK_WORDSHIFT] |= (1 << (bitno&IMASK_BITMASK));
177 static inline void
178 imask_clrbit(imask_t *idp, int bitno)
180 idp->bits[bitno>>IMASK_WORDSHIFT] &= ~(1 << (bitno&IMASK_BITMASK));
183 static inline void
184 imask_clrbit_v(volatile imask_t *idp, int bitno)
186 idp->bits[bitno>>IMASK_WORDSHIFT] &= ~(1 << (bitno&IMASK_BITMASK));
189 static inline u_int32_t
190 imask_andbit_v(const volatile imask_t *idp, int bitno)
192 return idp->bits[bitno>>IMASK_WORDSHIFT] & (1 << (bitno&IMASK_BITMASK));
195 static inline int
196 imask_test_v(const volatile imask_t *idp, const imask_t *isp)
198 return ((idp->bits[IMASK_ICU_LO] & isp->bits[IMASK_ICU_LO]) ||
199 (idp->bits[IMASK_ICU_HI] & isp->bits[IMASK_ICU_HI]) ||
200 (idp->bits[IMASK_ICU_GPP] & isp->bits[IMASK_ICU_GPP])||
201 (idp->bits[IMASK_SOFTINT] & isp->bits[IMASK_SOFTINT]));
204 #ifdef EXT_INTR_STATS
206 * ISR timing stats
209 typedef struct ext_intr_hist {
210 u_int64_t tcause;
211 u_int64_t tcommit;
212 u_int64_t tstart;
213 u_int64_t tfin;
214 } ext_intr_hist_t __attribute__ ((aligned(32)));
216 typedef struct ext_intr_stat {
217 struct ext_intr_hist *histp;
218 unsigned int histix;
219 u_int64_t cnt;
220 u_int64_t sum;
221 u_int64_t min;
222 u_int64_t max;
223 u_int64_t pnd;
224 u_int64_t borrowed;
225 struct ext_intr_stat *save;
226 unsigned long preempted[NIRQ]; /* XXX */
227 } ext_intr_stat_t __attribute__ ((aligned(32)));
229 extern int intr_depth_max;
230 extern int ext_intr_stats_enb;
231 extern ext_intr_stat_t ext_intr_stats[];
232 extern ext_intr_stat_t *ext_intr_statp;
234 extern void ext_intr_stats_init(void);
235 extern void ext_intr_stats_cause
236 (u_int32_t, u_int32_t, u_int32_t, u_int32_t);
237 extern void ext_intr_stats_pend
238 (u_int32_t, u_int32_t, u_int32_t, u_int32_t);
239 extern void ext_intr_stats_commit(imask_t *);
240 extern void ext_intr_stats_commit_m(imask_t *);
241 extern void ext_intr_stats_commit_irq(u_int);
242 extern u_int64_t ext_intr_stats_pre(int);
243 extern void ext_intr_stats_post(int, u_int64_t);
245 #define EXT_INTR_STATS_INIT() ext_intr_stats_init()
246 #define EXT_INTR_STATS_CAUSE(l, h, g, s) ext_intr_stats_cause(l, h, g, s)
247 #define EXT_INTR_STATS_COMMIT_M(m) ext_intr_stats_commit_m(m)
248 #define EXT_INTR_STATS_COMMIT_IRQ(i) ext_intr_stats_commit_irq(i)
249 #define EXT_INTR_STATS_DECL(t) u_int64_t t
250 #define EXT_INTR_STATS_PRE(i, t) t = ext_intr_stats_pre(i)
251 #define EXT_INTR_STATS_POST(i, t) ext_intr_stats_post(i, t)
252 #define EXT_INTR_STATS_PEND(l, h, g, s) ext_intr_stats_pend(l, h, g, s)
253 #define EXT_INTR_STATS_PEND_IRQ(i) ext_intr_stats[i].pnd++
254 #define EXT_INTR_STATS_DEPTH() \
255 intr_depth_max = (intr_depth > intr_depth_max) ? \
256 intr_depth : intr_depth_max
258 #else /* EXT_INTR_STATS */
260 #define EXT_INTR_STATS_INIT()
261 #define EXT_INTR_STATS_CAUSE(l, h, g, s)
262 #define EXT_INTR_STATS_COMMIT_M(m)
263 #define EXT_INTR_STATS_COMMIT_IRQ(i)
264 #define EXT_INTR_STATS_DECL(t)
265 #define EXT_INTR_STATS_PRE(irq, t)
266 #define EXT_INTR_STATS_POST(i, t)
267 #define EXT_INTR_STATS_PEND(l, h, g, s)
268 #define EXT_INTR_STATS_PEND_IRQ(i)
269 #define EXT_INTR_STATS_DEPTH()
271 #endif /* EXT_INTR_STATS */
274 #ifdef SPL_STATS
275 typedef struct spl_hist {
276 int level;
277 void *addr;
278 u_int64_t time;
279 } spl_hist_t;
281 extern void spl_stats_init();
282 extern void spl_stats_log();
283 extern unsigned int spl_stats_enb;
285 #define SPL_STATS_INIT() spl_stats_init()
286 #define SPL_STATS_LOG(ipl, cc) spl_stats_log((ipl), (cc))
288 #else
290 #define SPL_STATS_INIT()
291 #define SPL_STATS_LOG(ipl, cc)
293 #endif /* SPL_STATS */
296 void intr_dispatch(void);
297 #ifdef SPL_INLINE
298 static inline int splraise(int);
299 static inline int spllower(int);
300 static inline void splx(int);
301 #else
302 extern int splraise(int);
303 extern int spllower(int);
304 extern void splx(int);
305 #endif
307 extern volatile int tickspending;
309 extern volatile imask_t ipending;
310 extern imask_t imask[];
313 * inlines for manipulating PSL_EE
315 static inline void
316 extintr_restore(register_t omsr)
318 __asm volatile ("sync; mtmsr %0;" :: "r"(omsr));
321 static inline register_t
322 extintr_enable(void)
324 register_t omsr;
326 __asm volatile("sync;");
327 __asm volatile("mfmsr %0;" : "=r"(omsr));
328 __asm volatile("mtmsr %0;" :: "r"(omsr | PSL_EE));
330 return omsr;
333 static inline register_t
334 extintr_disable(void)
336 register_t omsr;
338 __asm volatile("mfmsr %0;" : "=r"(omsr));
339 __asm volatile("mtmsr %0;" :: "r"(omsr & ~PSL_EE));
340 __asm volatile("isync;");
342 return omsr;
345 #ifdef SPL_INLINE
346 static inline int
347 splraise(int ncpl)
349 int ocpl;
350 register_t omsr;
352 omsr = extintr_disable();
353 ocpl = cpl;
354 if (ncpl > cpl) {
355 SPL_STATS_LOG(ncpl, 0);
356 cpl = ncpl;
357 if ((ncpl == IPL_HIGH) && ((omsr & PSL_EE) != 0)) {
358 /* leave external interrupts disabled */
359 return (ocpl | IPL_EE);
362 extintr_restore(omsr);
363 return (ocpl);
366 static inline void
367 splx(int xcpl)
369 imask_t *ncplp;
370 register_t omsr;
371 int ncpl = xcpl & IPL_PRIMASK;
373 ncplp = &imask[ncpl];
375 omsr = extintr_disable();
376 if (ncpl < cpl) {
377 cpl = ncpl;
378 SPL_STATS_LOG(ncpl, 0);
379 if (imask_test_v(&ipending, ncplp))
380 intr_dispatch();
382 if (xcpl & IPL_EE)
383 omsr |= PSL_EE;
384 extintr_restore(omsr);
387 static inline int
388 spllower(int ncpl)
390 int ocpl;
391 imask_t *ncplp;
392 register_t omsr;
394 ncpl &= IPL_PRIMASK;
395 ncplp = &imask[ncpl];
397 omsr = extintr_disable();
398 ocpl = cpl;
399 cpl = ncpl;
400 SPL_STATS_LOG(ncpl, 0);
401 #ifdef EXT_INTR_STATS
402 ext_intr_statp = 0;
403 #endif
404 if (imask_test_v(&ipending, ncplp))
405 intr_dispatch();
407 if (ncpl < IPL_HIGH)
408 omsr |= PSL_EE;
409 extintr_restore(omsr);
411 return (ocpl);
413 #endif /* SPL_INLINE */
417 * Soft interrupt IRQs
418 * see also intrnames[] in locore.S
420 #define SIR_BASE (NIRQ-32)
421 #define SIXBIT(ipl) ((ipl) - SIR_BASE) /* XXX rennovate later */
422 #define SIR_SOFTCLOCK (NIRQ-5)
423 #define SIR_CLOCK SIXBIT(SIR_SOFTCLOCK) /* XXX rennovate later */
424 #define SIR_SOFTNET (NIRQ-4)
425 #define SIR_SOFTBIO (NIRQ-3)
426 #define SIR_SOFTSERIAL (NIRQ-2)
427 #define SIR_HWCLOCK (NIRQ-1)
428 #define SPL_CLOCK SIXBIT(SIR_HWCLOCK) /* XXX rennovate later */
429 #define SIR_RES ~(SIBIT(SIR_SOFTCLOCK)|\
430 SIBIT(SIR_SOFTNET)|\
431 SIBIT(SIR_SOFTBIO)|\
432 SIBIT(SIR_SOFTSERIAL)|\
433 SIBIT(SIR_HWCLOCK))
435 struct intrhand;
438 * Miscellaneous
440 #define spl0() spllower(IPL_NONE)
442 typedef int ipl_t;
443 typedef struct {
444 ipl_t _ipl;
445 } ipl_cookie_t;
447 static inline ipl_cookie_t
448 makeiplcookie(ipl_t ipl)
451 return (ipl_cookie_t){._ipl = ipl};
454 static inline int
455 splraiseipl(ipl_cookie_t icookie)
458 return splraise(icookie._ipl);
461 #include <sys/spl.h>
463 #define SIBIT(ipl) (1 << ((ipl) - SIR_BASE))
465 void *intr_establish(int, int, int, int (*)(void *), void *);
466 void intr_disestablish(void *);
467 void init_interrupt(void);
468 const char * intr_typename(int);
469 const char * intr_string(int);
470 const struct evcnt * intr_evcnt(int);
471 void ext_intr(struct intrframe *);
473 /* the following are needed to compile until this port is properly
474 * converted to ppcoea-rennovation.
476 void genppc_cpu_configure(void);
478 void strayintr(int);
481 * defines for indexing intrcnt
483 #define CNT_IRQ0 0
484 #define CNT_CLOCK SIR_HWCLOCK
485 #define CNT_SOFTCLOCK SIR_SOFTCLOCK
486 #define CNT_SOFTNET SIR_NET
487 #define CNT_SOFTSERIAL SIR_SOFTSERIAL
488 #define CNT_SOFTBIO SIR_BIO
490 #endif /* !_LOCORE */
492 #endif /* _MVPPPC_INTR_H_ */