1 /* $NetBSD: sb1250_icu.c,v 1.2 2002/03/06 07:51:02 simonb Exp $ */ 2 3 /* 4 * Copyright 2000, 2001 5 * Broadcom Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and copied only 8 * in accordance with the following terms and conditions. Subject to these 9 * conditions, you may download, copy, install, use, modify and distribute 10 * modified or unmodified copies of this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce and 14 * retain this copyright notice and list of conditions as they appear in 15 * the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Broadcom Corporation. Neither the "Broadcom Corporation" name nor any 19 * trademark or logo of Broadcom Corporation may be used to endorse or 20 * promote products derived from this software without the prior written 21 * permission of Broadcom Corporation. 22 * 23 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 24 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 26 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 27 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 28 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 39 /* XXX for uvmexp */ 40 #include <uvm/uvm_extern.h> 41 42 #include <machine/systemsw.h> 43 #include <mips/locore.h> 44 45 /* XXX for now, this copes with one cpu only, and assumes it's CPU 0 */ 46 47 /* imr values corresponding to each pin */ 48 uint64_t ints_for_line[6]; 49 uint64_t imr_all; 50 51 struct sb1250_ihand { 52 void (*fun)(void *, uint32_t, uint32_t); 53 void *arg; 54 int level; 55 }; 56 static struct sb1250_ihand sb1250_ihands[64]; /* XXX */ 57 58 #define SB1250_I_IMR_ADDR (MIPS_PHYS_TO_KSEG1(0x10020000 + 0x0028)) 59 #define SB1250_I_IMR_SSTATUS (MIPS_PHYS_TO_KSEG1(0x10020000 + 0x0040)) 60 #define SB1250_I_MAP(x) \ 61 (MIPS_PHYS_TO_KSEG1(0x10020000 + 0x0200 + (x) * 8)) 62 #define SB1250_I_MAP_I0 0x00 63 #define SB1250_I_MAP_I1 0x01 64 #define SB1250_I_MAP_I2 0x02 65 /* XXX */ 66 67 #define READ_REG(rp) (mips3_ld((uint64_t *)(rp))) 68 #define WRITE_REG(rp, val) (mips3_sd((uint64_t *)(rp), (val))) 69 70 #undef __inline 71 #define __inline 72 73 static void sb1250_cpu_intr(uint32_t, uint32_t, uint32_t, uint32_t); 74 static void sb1250_cpu_setsoftintr(void); 75 static void *sb1250_intr_establish(u_int, u_int, 76 void (*fun)(void *, uint32_t, uint32_t), void *); 77 78 void 79 sb1250_icu_init(void) 80 { 81 int i; 82 83 /* zero out the list of used interrupts/lines */ 84 memset(ints_for_line, 0, sizeof ints_for_line); 85 imr_all = 0xffffffffffffffff; 86 memset(sb1250_ihands, 0, sizeof sb1250_ihands); 87 88 systemsw.s_cpu_intr = sb1250_cpu_intr; 89 systemsw.s_cpu_setsoftintr = sb1250_cpu_setsoftintr; 90 systemsw.s_intr_establish = sb1250_intr_establish; 91 92 WRITE_REG(SB1250_I_IMR_ADDR, imr_all); 93 94 for (i = 0; i < 64; i++) 95 WRITE_REG(SB1250_I_MAP(i), SB1250_I_MAP_I0); 96 } 97 98 static void 99 sb1250_cpu_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending) 100 { 101 int i, j, s; 102 uint64_t sstatus; 103 uint32_t cycles; 104 105 uvmexp.intrs++; 106 107 s = splhigh(); /* XXX */ 108 109 /* XXX do something if 5? */ 110 if (ipending & (MIPS_INT_MASK_0 << 5)) { 111 cycles = mips3_cp0_count_read(); 112 mips3_cp0_compare_write(cycles - 1); 113 /* just leave the bugger disabled */ 114 } 115 116 for (i = 4; i >= 0; i--) { 117 if (ipending & (MIPS_INT_MASK_0 << i)) { 118 119 sstatus = READ_REG(SB1250_I_IMR_SSTATUS); 120 sstatus &= ints_for_line[i]; 121 for (j = 0; sstatus != 0 && j < 64; j++) { 122 if (sstatus & ((uint64_t)1 << j)) { 123 struct sb1250_ihand *ihp = &sb1250_ihands[j]; 124 (*ihp->fun)(ihp->arg, status, pc); 125 sstatus &= ~((uint64_t)1 << j); 126 } 127 } 128 } 129 cause &= ~(MIPS_INT_MASK_0 << i); 130 #if 0 131 _splset((status & ~cause & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE); 132 #endif 133 } 134 135 /* software interrupt */ 136 if (ipending & MIPS_SOFT_INT_MASK_0) { 137 _clrsoftintr(MIPS_SOFT_INT_MASK_0); 138 uvmexp.softs++; 139 dosoftints(); 140 141 cause &= MIPS_SOFT_INT_MASK_0; 142 #if 0 143 _splset((status & ~cause & MIPS_INT_MASK) | MIPS_SR_INT_IE); 144 #endif 145 } 146 147 splx(s); /* XXX */ 148 } 149 150 static void 151 sb1250_cpu_setsoftintr(void) 152 { 153 154 _setsoftintr(MIPS_SOFT_INT_MASK_0); 155 } 156 157 static void * 158 sb1250_intr_establish(u_int num, u_int ipl, 159 void (*fun)(void *, uint32_t, uint32_t), void *arg) 160 { 161 int s, line; 162 163 s = splhigh(); 164 165 if (num >= 64) /* XXX */ 166 panic("invalid interrupt number (0x%x)", num); 167 if (ipl >= _NIPL) 168 panic("invalid ipl (0x%x)", ipl); 169 170 if (sb1250_ihands[num].fun != NULL) 171 panic("cannot share sb1250 interrupts"); 172 173 /* XXX for now, everything on I0 */ 174 switch (ipl) { 175 #if 0 176 case IPL_NMI: 177 sr_mask = XXX; 178 break; 179 case IPL_STATCLOCK: 180 sr_mask = XXX; 181 break; 182 case IPL_CLOCK: 183 sr_mask = XXX; 184 break; 185 #endif 186 default: 187 line = 0; 188 break; 189 } 190 191 ints_for_line[line] |= (1ULL << num); 192 imr_all &= ~(1ULL << num); 193 194 /* XXX map ! */ 195 196 sb1250_ihands[num].fun = fun; 197 sb1250_ihands[num].arg = arg; 198 sb1250_ihands[num].level = ipl; 199 200 WRITE_REG(SB1250_I_IMR_ADDR, imr_all); 201 202 splx(s); 203 204 return (&sb1250_ihands[num]); 205 } 206