Home | History | Annotate | Line # | Download | only in marvell
marvell_intr.h revision 1.14
      1 /*	$NetBSD: marvell_intr.h,v 1.14 2008/04/24 11:36:51 he Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Charles M. Hannum.
      9  *
     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.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #ifndef _MVPPPC_INTR_H_
     40 #define _MVPPPC_INTR_H_
     41 
     42 #include <powerpc/psl.h>
     43 #include <powerpc/frame.h>
     44 
     45 /*
     46  * Interrupt Priority Levels
     47  */
     48 #define	IPL_NONE	0	/* nothing */
     49 #define	IPL_SOFTCLOCK	1	/* timeouts */
     50 #define	IPL_SOFTBIO	2	/* block I/O */
     51 #define	IPL_SOFTNET	3	/* protocol stacks */
     52 #define	IPL_SOFTSERIAL	4	/* serial */
     53 #define	IPL_VM		12	/* memory allocation */
     54 #define	IPL_SCHED	14	/* clock */
     55 #define	IPL_HIGH	15	/* everything */
     56 #define	NIPL		16
     57 #define IPL_PRIMASK	0xf
     58 #define IPL_EE		0x10	/* enable external interrupts on splx */
     59 
     60 /* Interrupt sharing types. */
     61 #define	IST_NONE	0	/* none */
     62 #define	IST_PULSE	1	/* pulsed */
     63 #define	IST_EDGE	2	/* edge-triggered */
     64 #define	IST_LEVEL	3	/* level-triggered */
     65 #define	IST_SOFT	4	/* software-triggered */
     66 #define	IST_CLOCK	5	/* exclusive for clock */
     67 #define	NIST		6
     68 
     69 #if !defined(_LOCORE) && defined(_KERNEL)
     70 
     71 #define	CLKF_BASEPRI(frame)	((frame)->pri == IPL_NONE)
     72 
     73 /*
     74  * we support 128 IRQs:
     75  *	96 (ICU_LEN) hard interrupt IRQs:
     76  *		- 64 Main Cause IRQs,
     77  *		- 32 GPP IRQs,
     78  *	and 32 softint IRQs
     79  */
     80 #define ICU_LEN		96	/* number of  HW IRQs */
     81 #define IRQ_GPP_BASE	64	/* base of GPP IRQs */
     82 #define IRQ_GPP_SUM	(32+24) /* GPP[7..0] interrupt */	/* XXX */
     83 #define NIRQ		128	/* total # of HW IRQs */
     84 
     85 #define IMASK_ICU_LO	0
     86 #define IMASK_ICU_HI	1
     87 #define IMASK_ICU_GPP	2
     88 #define IMASK_SOFTINT	3
     89 #define IMASK_WORDSHIFT 5	/* log2(32) */
     90 #define IMASK_BITMASK	~((~0) << IMASK_WORDSHIFT)
     91 
     92 #define IRQ_IS_GPP(irq) ((irq >= IRQ_GPP_BASE) && (irq < ICU_LEN))
     93 
     94 /*
     95  * interrupt mask bit vector
     96  */
     97 typedef struct {
     98 	u_int32_t bits[4];
     99 } imask_t __attribute__ ((aligned(16)));
    100 
    101 static inline void imask_zero(imask_t *);
    102 static inline void imask_zero_v(volatile imask_t *);
    103 static inline void imask_dup_v(imask_t *, const volatile imask_t *);
    104 static inline void imask_and(imask_t *, const imask_t *);
    105 static inline void imask_andnot_v(volatile imask_t *, const imask_t *);
    106 static inline void imask_andnot_icu_vv(volatile imask_t *, const volatile imask_t *);
    107 static inline int imask_empty(const imask_t *);
    108 static inline void imask_orbit(imask_t *, int);
    109 static inline void imask_orbit_v(volatile imask_t *, int);
    110 static inline void imask_clrbit(imask_t *, int);
    111 static inline void imask_clrbit_v(volatile imask_t *, int);
    112 static inline u_int32_t imask_andbit_v(const volatile imask_t *, int);
    113 static inline int imask_test_v(const volatile imask_t *, const imask_t *);
    114 
    115 static inline void
    116 imask_zero(imask_t *idp)
    117 {
    118 	idp->bits[IMASK_ICU_LO]  = 0;
    119 	idp->bits[IMASK_ICU_HI]  = 0;
    120 	idp->bits[IMASK_ICU_GPP] = 0;
    121 	idp->bits[IMASK_SOFTINT] = 0;
    122 }
    123 
    124 static inline void
    125 imask_zero_v(volatile imask_t *idp)
    126 {
    127 	idp->bits[IMASK_ICU_LO]  = 0;
    128 	idp->bits[IMASK_ICU_HI]  = 0;
    129 	idp->bits[IMASK_ICU_GPP] = 0;
    130 	idp->bits[IMASK_SOFTINT] = 0;
    131 }
    132 
    133 static inline void
    134 imask_dup_v(imask_t *idp, const volatile imask_t *isp)
    135 {
    136 	*idp = *isp;
    137 }
    138 
    139 static inline void
    140 imask_and(imask_t *idp, const imask_t *isp)
    141 {
    142 	idp->bits[IMASK_ICU_LO]  &= isp->bits[IMASK_ICU_LO];
    143 	idp->bits[IMASK_ICU_HI]  &= isp->bits[IMASK_ICU_HI];
    144 	idp->bits[IMASK_ICU_GPP] &= isp->bits[IMASK_ICU_GPP];
    145 	idp->bits[IMASK_SOFTINT] &= isp->bits[IMASK_SOFTINT];
    146 }
    147 
    148 static inline void
    149 imask_andnot_v(volatile imask_t *idp, const imask_t *isp)
    150 {
    151 	idp->bits[IMASK_ICU_LO]  &= ~isp->bits[IMASK_ICU_LO];
    152 	idp->bits[IMASK_ICU_HI]  &= ~isp->bits[IMASK_ICU_HI];
    153 	idp->bits[IMASK_ICU_GPP] &= ~isp->bits[IMASK_ICU_GPP];
    154 	idp->bits[IMASK_SOFTINT] &= ~isp->bits[IMASK_SOFTINT];
    155 }
    156 
    157 static inline void
    158 imask_andnot_icu_vv(volatile imask_t *idp, const volatile imask_t *isp)
    159 {
    160 	idp->bits[IMASK_ICU_LO]  &= ~isp->bits[IMASK_ICU_LO];
    161 	idp->bits[IMASK_ICU_HI]  &= ~isp->bits[IMASK_ICU_HI];
    162 	idp->bits[IMASK_ICU_GPP] &= ~isp->bits[IMASK_ICU_GPP];
    163 }
    164 
    165 static inline int
    166 imask_empty(const imask_t *isp)
    167 {
    168 	return (! (isp->bits[IMASK_ICU_LO] | isp->bits[IMASK_ICU_HI] |
    169 		   isp->bits[IMASK_ICU_GPP]| isp->bits[IMASK_SOFTINT]));
    170 }
    171 
    172 static inline void
    173 imask_orbit(imask_t *idp, int bitno)
    174 {
    175 	idp->bits[bitno>>IMASK_WORDSHIFT] |= (1 << (bitno&IMASK_BITMASK));
    176 }
    177 
    178 static inline void
    179 imask_orbit_v(volatile imask_t *idp, int bitno)
    180 {
    181 	idp->bits[bitno>>IMASK_WORDSHIFT] |= (1 << (bitno&IMASK_BITMASK));
    182 }
    183 
    184 static inline void
    185 imask_clrbit(imask_t *idp, int bitno)
    186 {
    187 	idp->bits[bitno>>IMASK_WORDSHIFT] &= ~(1 << (bitno&IMASK_BITMASK));
    188 }
    189 
    190 static inline void
    191 imask_clrbit_v(volatile imask_t *idp, int bitno)
    192 {
    193 	idp->bits[bitno>>IMASK_WORDSHIFT] &= ~(1 << (bitno&IMASK_BITMASK));
    194 }
    195 
    196 static inline u_int32_t
    197 imask_andbit_v(const volatile imask_t *idp, int bitno)
    198 {
    199 	return idp->bits[bitno>>IMASK_WORDSHIFT] & (1 << (bitno&IMASK_BITMASK));
    200 }
    201 
    202 static inline int
    203 imask_test_v(const volatile imask_t *idp, const imask_t *isp)
    204 {
    205 	return ((idp->bits[IMASK_ICU_LO]  & isp->bits[IMASK_ICU_LO]) ||
    206 		(idp->bits[IMASK_ICU_HI]  & isp->bits[IMASK_ICU_HI]) ||
    207 		(idp->bits[IMASK_ICU_GPP] & isp->bits[IMASK_ICU_GPP])||
    208 		(idp->bits[IMASK_SOFTINT] & isp->bits[IMASK_SOFTINT]));
    209 }
    210 
    211 #ifdef EXT_INTR_STATS
    212 /*
    213  * ISR timing stats
    214  */
    215 
    216 typedef struct ext_intr_hist {
    217 	u_int64_t tcause;
    218 	u_int64_t tcommit;
    219 	u_int64_t tstart;
    220 	u_int64_t tfin;
    221 } ext_intr_hist_t __attribute__ ((aligned(32)));
    222 
    223 typedef struct ext_intr_stat {
    224         struct ext_intr_hist *histp;
    225         unsigned int histix;
    226         u_int64_t cnt;
    227         u_int64_t sum;
    228         u_int64_t min;
    229         u_int64_t max;
    230         u_int64_t pnd;
    231         u_int64_t borrowed;
    232         struct ext_intr_stat *save;
    233 	unsigned long preempted[NIRQ];	/* XXX */
    234 } ext_intr_stat_t  __attribute__ ((aligned(32)));
    235 
    236 extern int intr_depth_max;
    237 extern int ext_intr_stats_enb;
    238 extern ext_intr_stat_t ext_intr_stats[];
    239 extern ext_intr_stat_t *ext_intr_statp;
    240 
    241 extern void ext_intr_stats_init __P((void));
    242 extern void ext_intr_stats_cause
    243 	__P((u_int32_t, u_int32_t, u_int32_t, u_int32_t));
    244 extern void ext_intr_stats_pend
    245 	__P((u_int32_t, u_int32_t, u_int32_t, u_int32_t));
    246 extern void ext_intr_stats_commit __P((imask_t *));
    247 extern void ext_intr_stats_commit_m __P((imask_t *));
    248 extern void ext_intr_stats_commit_irq __P((u_int));
    249 extern u_int64_t ext_intr_stats_pre  __P((int));
    250 extern void ext_intr_stats_post __P((int, u_int64_t));
    251 
    252 #define EXT_INTR_STATS_INIT() ext_intr_stats_init()
    253 #define EXT_INTR_STATS_CAUSE(l, h, g, s)  ext_intr_stats_cause(l, h, g, s)
    254 #define EXT_INTR_STATS_COMMIT_M(m) ext_intr_stats_commit_m(m)
    255 #define EXT_INTR_STATS_COMMIT_IRQ(i) ext_intr_stats_commit_irq(i)
    256 #define EXT_INTR_STATS_DECL(t) u_int64_t t
    257 #define EXT_INTR_STATS_PRE(i, t) t = ext_intr_stats_pre(i)
    258 #define EXT_INTR_STATS_POST(i, t) ext_intr_stats_post(i, t)
    259 #define EXT_INTR_STATS_PEND(l, h, g, s) ext_intr_stats_pend(l, h, g, s)
    260 #define EXT_INTR_STATS_PEND_IRQ(i) ext_intr_stats[i].pnd++
    261 #define EXT_INTR_STATS_DEPTH() \
    262 		 intr_depth_max = (intr_depth > intr_depth_max) ? \
    263 			 intr_depth : intr_depth_max
    264 
    265 #else /* EXT_INTR_STATS */
    266 
    267 #define EXT_INTR_STATS_INIT()
    268 #define EXT_INTR_STATS_CAUSE(l, h, g, s)
    269 #define EXT_INTR_STATS_COMMIT_M(m)
    270 #define EXT_INTR_STATS_COMMIT_IRQ(i)
    271 #define EXT_INTR_STATS_DECL(t)
    272 #define EXT_INTR_STATS_PRE(irq, t)
    273 #define EXT_INTR_STATS_POST(i, t)
    274 #define EXT_INTR_STATS_PEND(l, h, g, s)
    275 #define EXT_INTR_STATS_PEND_IRQ(i)
    276 #define EXT_INTR_STATS_DEPTH()
    277 
    278 #endif	/* EXT_INTR_STATS */
    279 
    280 
    281 #ifdef SPL_STATS
    282 typedef struct spl_hist {
    283 	int level;
    284 	void *addr;
    285 	u_int64_t time;
    286 } spl_hist_t;
    287 
    288 extern  void spl_stats_init();
    289 extern  void spl_stats_log();
    290 extern unsigned int spl_stats_enb;
    291 
    292 #define SPL_STATS_INIT()	spl_stats_init()
    293 #define SPL_STATS_LOG(ipl, cc)	spl_stats_log((ipl), (cc))
    294 
    295 #else
    296 
    297 #define SPL_STATS_INIT()
    298 #define SPL_STATS_LOG(ipl, cc)
    299 
    300 #endif	/* SPL_STATS */
    301 
    302 
    303 void intr_dispatch __P((void));
    304 #ifdef SPL_INLINE
    305 static inline int splraise __P((int));
    306 static inline int spllower __P((int));
    307 static inline void splx __P((int));
    308 #else
    309 extern int splraise __P((int));
    310 extern int spllower __P((int));
    311 extern void splx __P((int));
    312 #endif
    313 
    314 extern volatile int tickspending;
    315 
    316 extern volatile imask_t ipending;
    317 extern imask_t imask[];
    318 
    319 /*
    320  * inlines for manipulating PSL_EE
    321  */
    322 static inline void
    323 extintr_restore(register_t omsr)
    324 {
    325 	__asm volatile ("sync; mtmsr %0;" :: "r"(omsr));
    326 }
    327 
    328 static inline register_t
    329 extintr_enable(void)
    330 {
    331 	register_t omsr;
    332 
    333 	__asm volatile("sync;");
    334 	__asm volatile("mfmsr %0;" : "=r"(omsr));
    335 	__asm volatile("mtmsr %0;" :: "r"(omsr | PSL_EE));
    336 
    337 	return omsr;
    338 }
    339 
    340 static inline register_t
    341 extintr_disable(void)
    342 {
    343 	register_t omsr;
    344 
    345 	__asm volatile("mfmsr %0;" : "=r"(omsr));
    346 	__asm volatile("mtmsr %0;" :: "r"(omsr & ~PSL_EE));
    347 	__asm volatile("isync;");
    348 
    349 	return omsr;
    350 }
    351 
    352 #ifdef SPL_INLINE
    353 static inline int
    354 splraise(int ncpl)
    355 {
    356 	int ocpl;
    357 	register_t omsr;
    358 
    359 	omsr = extintr_disable();
    360 	ocpl = cpl;
    361         if (ncpl > cpl) {
    362 		SPL_STATS_LOG(ncpl, 0);
    363                 cpl = ncpl;
    364 		if ((ncpl == IPL_HIGH) && ((omsr & PSL_EE) != 0)) {
    365 			/* leave external interrupts disabled */
    366 			return (ocpl | IPL_EE);
    367 		}
    368 	}
    369         extintr_restore(omsr);
    370         return (ocpl);
    371 }
    372 
    373 static inline void
    374 splx(int xcpl)
    375 {
    376 	imask_t *ncplp;
    377 	register_t omsr;
    378 	int ncpl = xcpl & IPL_PRIMASK;
    379 
    380 	ncplp = &imask[ncpl];
    381 
    382 	omsr = extintr_disable();
    383 	if (ncpl < cpl) {
    384 		cpl = ncpl;
    385 		SPL_STATS_LOG(ncpl, 0);
    386 		if (imask_test_v(&ipending, ncplp))
    387 			intr_dispatch();
    388 	}
    389 	if (xcpl & IPL_EE)
    390 		omsr |= PSL_EE;
    391 	extintr_restore(omsr);
    392 }
    393 
    394 static inline int
    395 spllower(int ncpl)
    396 {
    397 	int ocpl;
    398 	imask_t *ncplp;
    399 	register_t omsr;
    400 
    401 	ncpl &= IPL_PRIMASK;
    402 	ncplp = &imask[ncpl];
    403 
    404 	omsr = extintr_disable();
    405 	ocpl = cpl;
    406 	cpl = ncpl;
    407 	SPL_STATS_LOG(ncpl, 0);
    408 #ifdef EXT_INTR_STATS
    409         ext_intr_statp = 0;
    410 #endif
    411 	if (imask_test_v(&ipending, ncplp))
    412 		intr_dispatch();
    413 
    414 	if (ncpl < IPL_HIGH)
    415 		omsr |= PSL_EE;
    416 	extintr_restore(omsr);
    417 
    418 	return (ocpl);
    419 }
    420 #endif	/* SPL_INLINE */
    421 
    422 
    423 /*
    424  * Soft interrupt IRQs
    425  * see also intrnames[] in locore.S
    426  */
    427 #define SIR_BASE	(NIRQ-32)
    428 #define SIXBIT(ipl)	((ipl) - SIR_BASE) /* XXX rennovate later */
    429 #define SIR_SOFTCLOCK	(NIRQ-5)
    430 #define SIR_CLOCK	SIXBIT(SIR_SOFTCLOCK) /* XXX rennovate later */
    431 #define SIR_SOFTNET	(NIRQ-4)
    432 #define SIR_SOFTBIO	(NIRQ-3)
    433 #define SIR_SOFTSERIAL	(NIRQ-2)
    434 #define SIR_HWCLOCK	(NIRQ-1)
    435 #define SPL_CLOCK	SIXBIT(SIR_HWCLOCK) /* XXX rennovate later */
    436 #define SIR_RES		~(SIBIT(SIR_SOFTCLOCK)|\
    437 			  SIBIT(SIR_SOFTNET)|\
    438 			  SIBIT(SIR_SOFTBIO)|\
    439 			  SIBIT(SIR_SOFTSERIAL)|\
    440 			  SIBIT(SIR_HWCLOCK))
    441 
    442 struct intrhand;
    443 
    444 /*
    445  * Miscellaneous
    446  */
    447 #define	spl0()		spllower(IPL_NONE)
    448 
    449 typedef int ipl_t;
    450 typedef struct {
    451 	ipl_t _ipl;
    452 } ipl_cookie_t;
    453 
    454 static inline ipl_cookie_t
    455 makeiplcookie(ipl_t ipl)
    456 {
    457 
    458 	return (ipl_cookie_t){._ipl = ipl};
    459 }
    460 
    461 static inline int
    462 splraiseipl(ipl_cookie_t icookie)
    463 {
    464 
    465 	return splraise(icookie._ipl);
    466 }
    467 
    468 #include <sys/spl.h>
    469 
    470 #define SIBIT(ipl)	(1 << ((ipl) - SIR_BASE))
    471 
    472 void	*intr_establish(int, int, int, int (*)(void *), void *);
    473 void	intr_disestablish(void *);
    474 void	init_interrupt(void);
    475 const char * intr_typename(int);
    476 const char * intr_string(int);
    477 const struct evcnt * intr_evcnt(int);
    478 void	ext_intr(struct intrframe *);
    479 
    480 /* the following are needed to compile until this port is properly
    481  * converted to ppcoea-rennovation.
    482  */
    483 void genppc_cpu_configure(void);
    484 
    485 void	strayintr(int);
    486 
    487 /*
    488  * defines for indexing intrcnt
    489  */
    490 #define CNT_IRQ0	0
    491 #define CNT_CLOCK	SIR_HWCLOCK
    492 #define CNT_SOFTCLOCK	SIR_SOFTCLOCK
    493 #define CNT_SOFTNET	SIR_NET
    494 #define CNT_SOFTSERIAL	SIR_SOFTSERIAL
    495 #define CNT_SOFTBIO	SIR_BIO
    496 
    497 #endif /* !_LOCORE */
    498 
    499 #endif /* _MVPPPC_INTR_H_ */
    500