Home | History | Annotate | Line # | Download | only in ews4800mips
      1 /*	$NetBSD: tr2_intr.c,v 1.12 2011/03/10 17:05:41 tsutsui Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2004, 2005 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by UCHIYAMA Yasushi.
      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  *
     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.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: tr2_intr.c,v 1.12 2011/03/10 17:05:41 tsutsui Exp $");
     34 
     35 #define	__INTR_PRIVATE
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/kernel.h>
     39 #include <sys/evcnt.h>
     40 #include <sys/cpu.h>
     41 #include <sys/lwp.h>
     42 #include <sys/intr.h>
     43 
     44 #include <machine/locore.h>	/* mips3_cp0* */
     45 #include <machine/sbdvar.h>
     46 #define	_SBD_TR2_PRIVATE
     47 #include <machine/sbd_tr2.h>
     48 
     49 #include <mips/cpuregs.h>
     50 
     51 SBD_DECL(tr2);
     52 
     53 const struct ipl_sr_map tr2_ipl_sr_map = {
     54     {
     55 	[IPL_NONE] =		0,
     56 	[IPL_SOFTCLOCK] =	MIPS_SOFT_INT_MASK_0,
     57 	[IPL_SOFTNET] =		MIPS_SOFT_INT_MASK,
     58 	[IPL_VM] =		MIPS_SOFT_INT_MASK
     59 				| MIPS_INT_MASK_0
     60 				| MIPS_INT_MASK_2
     61 				| MIPS_INT_MASK_4,
     62 	[IPL_SCHED] =		MIPS_SOFT_INT_MASK
     63 				| MIPS_INT_MASK_0
     64 				| MIPS_INT_MASK_2
     65 				| MIPS_INT_MASK_4
     66 				| MIPS_INT_MASK_5,
     67 	[IPL_DDB] =		MIPS_INT_MASK,
     68 	[IPL_HIGH] =		MIPS_INT_MASK,
     69 	/* !!! TEST !!! VME INTERRUPT IS NOT MASKED */
     70     },
     71 };
     72 
     73 #define	NIRQ		8
     74 struct tr2_intr_handler {
     75 	int (*func)(void *);
     76 	void *arg;
     77 	volatile uint8_t *picnic_reg;
     78 	uint8_t picnic_mask;
     79 	struct evcnt evcnt;
     80 	char evname[32];
     81 } tr2_intr_handler[NIRQ] = {
     82 	[0] = { NULL, NULL, PICNIC_INT4_MASK_REG, PICNIC_INT_KBMS },
     83 	[2] = { NULL, NULL, PICNIC_INT4_MASK_REG, PICNIC_INT_SERIAL },
     84 	[5] = { NULL, NULL, PICNIC_INT2_MASK_REG, PICNIC_INT_SCSI },
     85 	[6] = { NULL, NULL, PICNIC_INT2_MASK_REG, PICNIC_INT_ETHER },
     86 	[7] = { NULL, NULL, PICNIC_INT0_MASK_REG, PICNIC_INT_FDDLPT },
     87 };
     88 
     89 struct evcnt timer_tr2_ev =
     90     EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "picnic", "timer");
     91 
     92 void
     93 tr2_intr_init(void)
     94 {
     95 	uint32_t a = (uint32_t)ews4800mips_nmi_vec;
     96 
     97 	/* Install dump button handler address to NVSRAM (jumped from ROM) */
     98 	*(NVSRAM_CDUMP_ADDR + 0) = (a >> 24) & 0xff;
     99 	*(NVSRAM_CDUMP_ADDR + 4) = (a >> 16) & 0xff;
    100 	*(NVSRAM_CDUMP_ADDR + 8) = (a >> 8) & 0xff;
    101 	*(NVSRAM_CDUMP_ADDR +12) = a & 0xff;
    102 
    103 	/* Disable external interrupts */
    104 	*PICNIC_INT0_MASK_REG = 0;
    105 	*PICNIC_INT2_MASK_REG = 0;
    106 	*PICNIC_INT4_MASK_REG = 0;
    107 	*PICNIC_INT5_MASK_REG = 0;
    108 
    109 	evcnt_attach_static(&timer_tr2_ev);
    110 }
    111 
    112 void *
    113 tr2_intr_establish(int irq, int (*func)(void *), void *arg)
    114 {
    115 	struct tr2_intr_handler *ih = &tr2_intr_handler[irq];
    116 	int s;
    117 
    118 	s = splhigh();
    119 	ih->func = func;
    120 	ih->arg = arg;
    121 	snprintf(ih->evname, sizeof(ih->evname), "irq %d", irq);
    122 	evcnt_attach_dynamic(&ih->evcnt, EVCNT_TYPE_INTR, NULL,
    123 	    "picnic", ih->evname);
    124 
    125 	*ih->picnic_reg |= ih->picnic_mask;
    126 	splx(s);
    127 
    128 	return (void *)irq;
    129 }
    130 
    131 void
    132 tr2_intr_disestablish(void *arg)
    133 {
    134 	int s, irq = (int)arg;
    135 	struct tr2_intr_handler *ih = &tr2_intr_handler[irq];
    136 
    137 	s = splhigh();
    138 	*ih->picnic_reg &= ~ih->picnic_mask;
    139 	ih->func = NULL;
    140 	ih->arg = NULL;
    141 	evcnt_detach(&ih->evcnt);
    142 	splx(s);
    143 }
    144 
    145 void
    146 tr2_intr(int ppl, vaddr_t pc, uint32_t status)
    147 {
    148 	struct tr2_intr_handler *ih;
    149 	struct clockframe cf;
    150 	uint32_t r, ipending;
    151 	int ipl;
    152 
    153 	while (ppl < (ipl = splintr(&ipending))) {
    154 		if (ipending & MIPS_INT_MASK_5) {	/* CLOCK */
    155 			cf.pc = pc;
    156 			cf.sr = status;
    157 			cf.intr = (curcpu()->ci_idepth > 1);
    158 
    159 			*PICNIC_INT5_STATUS_REG = 0;
    160 			r = *PICNIC_INT5_STATUS_REG;
    161 
    162 			hardclock(&cf);
    163 			timer_tr2_ev.ev_count++;
    164 		}
    165 
    166 		if (ipending & MIPS_INT_MASK_4) {	/* KBD, MOUSE, SERIAL */
    167 			r = *PICNIC_INT4_STATUS_REG;
    168 
    169 			if (r & PICNIC_INT_KBMS) {
    170 				ih = &tr2_intr_handler[0];
    171 				if (ih->func) {
    172 					ih->func(ih->arg);
    173 					ih->evcnt.ev_count++;
    174 				}
    175 				r &= ~PICNIC_INT_KBMS;
    176 			}
    177 
    178 			if (r & PICNIC_INT_SERIAL) {
    179 #if 0
    180 				printf("SIO interrupt\n");
    181 #endif
    182 				ih = &tr2_intr_handler[2];
    183 				if (ih->func) {
    184 					ih->func(ih->arg);
    185 					ih->evcnt.ev_count++;
    186 				}
    187 				r &= ~PICNIC_INT_SERIAL;
    188 			}
    189 		}
    190 
    191 		if (ipending & MIPS_INT_MASK_3) {	/* VME */
    192 			printf("VME interrupt\n");
    193 
    194 			r = *(volatile uint32_t *)0xbfb00018; /* NABI? */
    195 			if ((r & 0x10) != 0) {
    196 				/* vme high interrupt */
    197 			} else if ((r & 0x4) != 0) {
    198 				/* vme lo interrupt */
    199 			} else {
    200 				/* error */
    201 			}
    202 		}
    203 
    204 		if (ipending & MIPS_INT_MASK_2) {	/* ETHER, SCSI */
    205 			r = *PICNIC_INT2_STATUS_REG;
    206 
    207 			if (r & PICNIC_INT_ETHER) {
    208 				ih = &tr2_intr_handler[6];
    209 				if (ih->func) {
    210 					ih->func(ih->arg);
    211 					ih->evcnt.ev_count++;
    212 				}
    213 				r &= ~PICNIC_INT_ETHER;
    214 			}
    215 
    216 			if (r & PICNIC_INT_SCSI) {
    217 				ih = &tr2_intr_handler[5];
    218 				if (ih->func) {
    219 					ih->func(ih->arg);
    220 					ih->evcnt.ev_count++;
    221 				}
    222 				r &= ~PICNIC_INT_SCSI;
    223 			}
    224 
    225 			if ((r & PICNIC_INT_FDDLPT) &&
    226 			    (ipending & MIPS_INT_MASK_5)) {
    227 #ifdef DEBUG
    228 				printf("FDD LPT interrupt\n");
    229 #endif
    230 				ih = &tr2_intr_handler[7];
    231 				if (ih->func) {
    232 					ih->func(ih->arg);
    233 					ih->evcnt.ev_count++;
    234 				}
    235 				r &= ~PICNIC_INT_FDDLPT;
    236 			}
    237 		}
    238 
    239 		if (ipending & MIPS_INT_MASK_1)
    240 			panic("unknown interrupt INT1\n");
    241 
    242 		if (ipending & MIPS_INT_MASK_0) {	/* FDD, PRINTER */
    243 #ifdef DEBUG
    244 			printf("printer, printer interrupt\n");
    245 #endif
    246 			r = *PICNIC_INT0_STATUS_REG;
    247 			if (r & PICNIC_INT_FDDLPT) {
    248 #ifdef DEBUG
    249 				printf("FDD, Printer interrupt.\n");
    250 #endif
    251 			} else {
    252 				printf("unknown interrupt INT0\n");
    253 			}
    254 		}
    255 	}
    256 }
    257 
    258 void
    259 tr2_initclocks(void)
    260 {
    261 
    262 	/* Enable clock interrupt */
    263 	*PICNIC_INT5_MASK_REG |= PICNIC_INT_CLOCK;
    264 }
    265