1 1.38 andvar /* $NetBSD: tx39icu.c,v 1.38 2022/07/21 10:09:21 andvar Exp $ */ 2 1.1 uch 3 1.9 uch /*- 4 1.14 uch * Copyright (c) 1999-2001 The NetBSD Foundation, Inc. 5 1.1 uch * All rights reserved. 6 1.1 uch * 7 1.9 uch * This code is derived from software contributed to The NetBSD Foundation 8 1.9 uch * by UCHIYAMA Yasushi. 9 1.9 uch * 10 1.1 uch * Redistribution and use in source and binary forms, with or without 11 1.1 uch * modification, are permitted provided that the following conditions 12 1.1 uch * are met: 13 1.1 uch * 1. Redistributions of source code must retain the above copyright 14 1.1 uch * notice, this list of conditions and the following disclaimer. 15 1.9 uch * 2. Redistributions in binary form must reproduce the above copyright 16 1.9 uch * notice, this list of conditions and the following disclaimer in the 17 1.9 uch * documentation and/or other materials provided with the distribution. 18 1.1 uch * 19 1.9 uch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.9 uch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.9 uch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.9 uch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.9 uch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.9 uch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.9 uch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.9 uch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.9 uch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.9 uch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.9 uch * POSSIBILITY OF SUCH DAMAGE. 30 1.1 uch */ 31 1.21 lukem 32 1.21 lukem #include <sys/cdefs.h> 33 1.38 andvar __KERNEL_RCSID(0, "$NetBSD: tx39icu.c,v 1.38 2022/07/21 10:09:21 andvar Exp $"); 34 1.9 uch 35 1.14 uch #include "opt_vr41xx.h" 36 1.14 uch #include "opt_tx39xx.h" 37 1.14 uch 38 1.1 uch #include "opt_use_poll.h" 39 1.16 uch #include "opt_tx39icu_debug.h" 40 1.1 uch #include "opt_tx39_watchdogtimer.h" 41 1.1 uch 42 1.30 tsutsui #define __INTR_PRIVATE 43 1.30 tsutsui 44 1.1 uch #include <sys/param.h> 45 1.1 uch #include <sys/systm.h> 46 1.1 uch #include <sys/device.h> 47 1.37 thorpej #include <sys/kmem.h> 48 1.1 uch #include <sys/queue.h> 49 1.26 uebayasi #include <sys/cpu.h> 50 1.1 uch 51 1.14 uch #include <uvm/uvm_extern.h> 52 1.14 uch 53 1.1 uch #include <mips/cpuregs.h> 54 1.1 uch #include <machine/bus.h> 55 1.30 tsutsui #include <machine/intr.h> 56 1.1 uch 57 1.1 uch #include <hpcmips/tx/tx39var.h> 58 1.1 uch #include <hpcmips/tx/tx39icureg.h> 59 1.5 uch #include <hpcmips/tx/tx39clockvar.h> 60 1.1 uch 61 1.1 uch #include <machine/cpu.h> 62 1.1 uch #include <dev/dec/clockvar.h> 63 1.1 uch 64 1.16 uch #undef TX39ICU_DEBUG_PRINT_PENDING_INTERRUPT /* For explorer. good luck! */ 65 1.1 uch 66 1.14 uch #if defined(VR41XX) && defined(TX39XX) 67 1.14 uch #define TX_INTR tx_intr 68 1.14 uch #else 69 1.14 uch #define TX_INTR cpu_intr /* locore_mips3 directly call this */ 70 1.14 uch #endif 71 1.30 tsutsui void TX_INTR(int, vaddr_t, uint32_t); 72 1.14 uch 73 1.16 uch #ifdef TX39ICU_DEBUG 74 1.16 uch #define DPRINTF_ENABLE 75 1.16 uch #define DPRINTF_DEBUG tx39icu_debug 76 1.1 uch #endif 77 1.16 uch #include <machine/debug.h> 78 1.16 uch 79 1.30 tsutsui uint32_t tx39intrvec; 80 1.1 uch 81 1.14 uch /* 82 1.14 uch * This is a mask of bits to clear in the SR when we go to a 83 1.14 uch * given interrupt priority level. 84 1.14 uch */ 85 1.30 tsutsui const struct ipl_sr_map __ipl_sr_map_tx = { 86 1.30 tsutsui .sr_bits = { 87 1.30 tsutsui [IPL_NONE] = 0, 88 1.30 tsutsui [IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0, 89 1.30 tsutsui [IPL_SOFTNET] = MIPS_SOFT_INT_MASK, 90 1.30 tsutsui [IPL_VM] = MIPS_SOFT_INT_MASK 91 1.30 tsutsui | MIPS_INT_MASK_2 92 1.30 tsutsui | MIPS_INT_MASK_4, 93 1.30 tsutsui [IPL_SCHED] = MIPS_SOFT_INT_MASK 94 1.30 tsutsui | MIPS_INT_MASK_2 95 1.30 tsutsui | MIPS_INT_MASK_4, 96 1.30 tsutsui [IPL_DDB] = MIPS_INT_MASK, 97 1.30 tsutsui [IPL_HIGH] = MIPS_INT_MASK, 98 1.30 tsutsui }, 99 1.14 uch }; 100 1.14 uch 101 1.1 uch /* IRQHIGH lines list */ 102 1.4 uch static const struct irqhigh_list { 103 1.1 uch int qh_pri; /* IRQHIGH priority */ 104 1.1 uch int qh_set; /* Register set */ 105 1.1 uch int qh_bit; /* bit offset in the register set */ 106 1.1 uch } irqhigh_list[] = { 107 1.1 uch {15, 5, 25}, /* POSPWROKINT */ 108 1.1 uch {15, 5, 24}, /* NEGPWROKINT */ 109 1.1 uch {14, 5, 30}, /* ALARMINT*/ 110 1.1 uch {13, 5, 29}, /* PERINT */ 111 1.1 uch #ifdef TX391X 112 1.1 uch {12, 2, 3}, /* MBUSPOSINT */ 113 1.1 uch {12, 2, 2}, /* MBUSNEGINT */ 114 1.1 uch {11, 2, 31}, /* UARTARXINT */ 115 1.1 uch {10, 2, 21}, /* UARTBRXINT */ 116 1.1 uch {9, 3, 19}, /* MFIOPOSINT19 */ 117 1.1 uch {9, 3, 18}, /* MFIOPOSINT18 */ 118 1.1 uch {9, 3, 17}, /* MFIOPOSINT17 */ 119 1.1 uch {9, 3, 16}, /* MFIOPOSINT16 */ 120 1.1 uch {8, 3, 1}, /* MFIOPOSINT1 */ 121 1.1 uch {8, 3, 0}, /* MFIOPOSINT0 */ 122 1.1 uch {8, 5, 13}, /* IOPOSINT6 */ 123 1.1 uch {8, 5, 12}, /* IOPOSINT5 */ 124 1.1 uch {7, 4, 19}, /* MFIONEGINT19 */ 125 1.1 uch {7, 4, 18}, /* MFIONEGINT18 */ 126 1.1 uch {7, 4, 17}, /* MFIONEGINT17 */ 127 1.1 uch {7, 4, 16}, /* MFIONEGINT16 */ 128 1.1 uch {6, 4, 1}, /* MFIONEGINT1 */ 129 1.1 uch {6, 4, 0}, /* MFIONEGINT0 */ 130 1.1 uch {6, 5, 6}, /* IONEGINT6 */ 131 1.1 uch {6, 5, 5}, /* IONEGINT5 */ 132 1.1 uch {5, 2, 5}, /* MBUSDMAFULLINT */ 133 1.1 uch #endif /* TX391X */ 134 1.1 uch #ifdef TX392X 135 1.1 uch {12, 2, 31}, /* UARTARXINT */ 136 1.1 uch {12, 2, 21}, /* UARTBRXINT */ 137 1.1 uch {11, 3, 19}, /* MFIOPOSINT19 */ 138 1.1 uch {11, 3, 18}, /* MFIOPOSINT18 */ 139 1.1 uch {11, 3, 17}, /* MFIOPOSINT17 */ 140 1.1 uch {11, 3, 16}, /* MFIOPOSINT16 */ 141 1.1 uch {10, 3, 1}, /* MFIOPOSINT1 */ 142 1.1 uch {10, 3, 0}, /* MFIOPOSINT0 */ 143 1.1 uch {10, 5, 13}, /* IOPOSINT6 */ 144 1.1 uch {10, 5, 12}, /* IOPOSINT5 */ 145 1.1 uch {9, 4, 19}, /* MFIONEGINT19 */ 146 1.1 uch {9, 4, 18}, /* MFIONEGINT18 */ 147 1.1 uch {9, 4, 17}, /* MFIONEGINT17 */ 148 1.1 uch {9, 4, 16}, /* MFIONEGINT16 */ 149 1.1 uch {8, 4, 1}, /* MFIONEGINT1 */ 150 1.1 uch {8, 4, 0}, /* MFIONEGINT0 */ 151 1.1 uch {8, 5, 6}, /* IONEGINT6 */ 152 1.1 uch {8, 5, 5}, /* IONEGINT5 */ 153 1.1 uch {5, 7, 19}, /* IRRXCINT */ 154 1.1 uch {5, 7, 17}, /* IRRXEINT */ 155 1.1 uch #endif /* TX392X */ 156 1.1 uch {4, 1, 18}, /* SNDDMACNTINT */ 157 1.1 uch {3, 1, 17}, /* TELDMACNTINT */ 158 1.1 uch {2, 1, 27}, /* CHIDMACNTINT */ 159 1.1 uch {1, 5, 7}, /* IOPOSINT0 */ 160 1.1 uch {1, 5, 0} /* IONEGINT0 */ 161 1.1 uch }; 162 1.1 uch 163 1.1 uch struct txintr_high_entry { 164 1.1 uch int he_set; 165 1.1 uch txreg_t he_mask; 166 1.12 uch int (*he_fun)(void *); 167 1.1 uch void *he_arg; 168 1.1 uch TAILQ_ENTRY(txintr_high_entry) he_link; 169 1.1 uch }; 170 1.1 uch 171 1.1 uch #ifdef USE_POLL 172 1.1 uch struct txpoll_entry{ 173 1.1 uch int p_cnt; /* dispatch interval */ 174 1.1 uch int p_desc; 175 1.12 uch int (*p_fun)(void *); 176 1.1 uch void *p_arg; 177 1.1 uch TAILQ_ENTRY(txpoll_entry) p_link; 178 1.1 uch }; 179 1.12 uch int tx39_poll_intr(void *); 180 1.1 uch #endif /* USE_POLL */ 181 1.1 uch 182 1.1 uch struct tx39icu_softc { 183 1.1 uch tx_chipset_tag_t sc_tc; 184 1.1 uch /* IRQLOW */ 185 1.1 uch txreg_t sc_le_mask[TX39_INTRSET_MAX + 1]; 186 1.12 uch int (*sc_le_fun[TX39_INTRSET_MAX + 1][32])(void *); 187 1.1 uch void *sc_le_arg[TX39_INTRSET_MAX + 1][32]; 188 1.1 uch /* IRQHIGH */ 189 1.1 uch TAILQ_HEAD(, txintr_high_entry) sc_he_head[TX39_IRQHIGH_MAX]; 190 1.1 uch /* Register */ 191 1.1 uch txreg_t sc_regs[TX39_INTRSET_MAX + 1]; 192 1.1 uch #ifdef USE_POLL 193 1.1 uch unsigned sc_pollcnt; 194 1.1 uch int sc_polling; 195 1.1 uch void *sc_poll_ih; 196 1.1 uch TAILQ_HEAD(, txpoll_entry) sc_p_head; 197 1.1 uch #endif /* USE_POLL */ 198 1.1 uch }; 199 1.1 uch 200 1.32 chs int tx39icu_match(device_t, cfdata_t, void *); 201 1.32 chs void tx39icu_attach(device_t, device_t, void *); 202 1.12 uch 203 1.12 uch void tx39_intr_dump(struct tx39icu_softc *); 204 1.12 uch void tx39_intr_decode(int, int *, int *); 205 1.12 uch void tx39_irqhigh_disestablish(tx_chipset_tag_t, int, int, int); 206 1.12 uch void tx39_irqhigh_establish(tx_chipset_tag_t, int, int, int, 207 1.12 uch int (*)(void *), void *); 208 1.31 tsutsui void tx39_irqhigh_intr(uint32_t, vaddr_t, uint32_t); 209 1.12 uch int tx39_irqhigh(int, int); 210 1.1 uch 211 1.32 chs CFATTACH_DECL_NEW(tx39icu, sizeof(struct tx39icu_softc), 212 1.20 thorpej tx39icu_match, tx39icu_attach, NULL, NULL); 213 1.1 uch 214 1.1 uch int 215 1.32 chs tx39icu_match(device_t parent, cfdata_t cf, void *aux) 216 1.1 uch { 217 1.14 uch 218 1.14 uch return (ATTACH_FIRST); 219 1.1 uch } 220 1.1 uch 221 1.1 uch void 222 1.32 chs tx39icu_attach(device_t parent, device_t self, void *aux) 223 1.1 uch { 224 1.1 uch struct txsim_attach_args *ta = aux; 225 1.32 chs struct tx39icu_softc *sc = device_private(self); 226 1.1 uch tx_chipset_tag_t tc = ta->ta_tc; 227 1.9 uch txreg_t reg, *regs; 228 1.1 uch int i; 229 1.14 uch 230 1.1 uch printf("\n"); 231 1.1 uch sc->sc_tc = ta->ta_tc; 232 1.1 uch 233 1.9 uch regs = sc->sc_regs; 234 1.9 uch regs[0] = tx_conf_read(tc, TX39_INTRSTATUS6_REG); 235 1.9 uch regs[1] = tx_conf_read(tc, TX39_INTRSTATUS1_REG); 236 1.9 uch regs[2] = tx_conf_read(tc, TX39_INTRSTATUS2_REG); 237 1.9 uch regs[3] = tx_conf_read(tc, TX39_INTRSTATUS3_REG); 238 1.9 uch regs[4] = tx_conf_read(tc, TX39_INTRSTATUS4_REG); 239 1.9 uch regs[5] = tx_conf_read(tc, TX39_INTRSTATUS5_REG); 240 1.1 uch #ifdef TX392X 241 1.9 uch regs[7] = tx_conf_read(tc, TX39_INTRSTATUS7_REG); 242 1.9 uch regs[8] = tx_conf_read(tc, TX39_INTRSTATUS8_REG); 243 1.1 uch #endif 244 1.16 uch #ifdef TX39ICU_DEBUG 245 1.2 uch printf("\t[Windows CE setting]\n"); 246 1.1 uch tx39_intr_dump(sc); 247 1.16 uch #endif /* TX39ICU_DEBUG */ 248 1.2 uch 249 1.1 uch #ifdef WINCE_DEFAULT_SETTING 250 1.1 uch #warning WINCE_DEFAULT_SETTING 251 1.1 uch #else /* WINCE_DEFAULT_SETTING */ 252 1.1 uch /* Disable IRQLOW */ 253 1.1 uch tx_conf_write(tc, TX39_INTRENABLE1_REG, 0); 254 1.1 uch tx_conf_write(tc, TX39_INTRENABLE2_REG, 0); 255 1.1 uch tx_conf_write(tc, TX39_INTRENABLE3_REG, 0); 256 1.1 uch tx_conf_write(tc, TX39_INTRENABLE4_REG, 0); 257 1.1 uch tx_conf_write(tc, TX39_INTRENABLE5_REG, 0); 258 1.1 uch #ifdef TX392X 259 1.1 uch tx_conf_write(tc, TX39_INTRENABLE7_REG, 0); 260 1.1 uch tx_conf_write(tc, TX39_INTRENABLE8_REG, 0); 261 1.1 uch #endif /* TX392X */ 262 1.1 uch 263 1.1 uch /* Disable IRQHIGH */ 264 1.1 uch reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 265 1.1 uch reg &= ~TX39_INTRENABLE6_PRIORITYMASK_MASK; 266 1.1 uch tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 267 1.1 uch #endif /* WINCE_DEFAULT_SETTING */ 268 1.1 uch 269 1.1 uch /* Clear all pending interrupts */ 270 1.4 uch tx_conf_write(tc, TX39_INTRCLEAR1_REG, 271 1.12 uch tx_conf_read(tc, TX39_INTRSTATUS1_REG)); 272 1.4 uch tx_conf_write(tc, TX39_INTRCLEAR2_REG, 273 1.12 uch tx_conf_read(tc, TX39_INTRSTATUS2_REG)); 274 1.4 uch tx_conf_write(tc, TX39_INTRCLEAR3_REG, 275 1.12 uch tx_conf_read(tc, TX39_INTRSTATUS3_REG)); 276 1.4 uch tx_conf_write(tc, TX39_INTRCLEAR4_REG, 277 1.12 uch tx_conf_read(tc, TX39_INTRSTATUS4_REG)); 278 1.4 uch tx_conf_write(tc, TX39_INTRCLEAR5_REG, 279 1.12 uch tx_conf_read(tc, TX39_INTRSTATUS5_REG)); 280 1.1 uch #ifdef TX392X 281 1.4 uch tx_conf_write(tc, TX39_INTRCLEAR7_REG, 282 1.12 uch tx_conf_read(tc, TX39_INTRSTATUS7_REG)); 283 1.4 uch tx_conf_write(tc, TX39_INTRCLEAR8_REG, 284 1.12 uch tx_conf_read(tc, TX39_INTRSTATUS8_REG)); 285 1.1 uch #endif /* TX392X */ 286 1.1 uch 287 1.1 uch /* Enable global interrupts */ 288 1.1 uch reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 289 1.1 uch reg |= TX39_INTRENABLE6_GLOBALEN; 290 1.1 uch tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 291 1.1 uch 292 1.1 uch /* Initialize IRQHIGH interrupt handler holder*/ 293 1.1 uch for (i = 0; i < TX39_IRQHIGH_MAX; i++) { 294 1.1 uch TAILQ_INIT(&sc->sc_he_head[i]); 295 1.1 uch } 296 1.1 uch #ifdef USE_POLL 297 1.1 uch /* Initialize polling handler holder */ 298 1.1 uch TAILQ_INIT(&sc->sc_p_head); 299 1.1 uch #endif /* USE_POLL */ 300 1.1 uch 301 1.1 uch /* Register interrupt module myself */ 302 1.1 uch tx_conf_register_intr(tc, self); 303 1.1 uch } 304 1.1 uch 305 1.14 uch void 306 1.30 tsutsui TX_INTR(int ppl, vaddr_t pc, uint32_t status) 307 1.1 uch { 308 1.30 tsutsui uint32_t ipending; 309 1.30 tsutsui int ipl; 310 1.1 uch struct tx39icu_softc *sc; 311 1.1 uch tx_chipset_tag_t tc; 312 1.9 uch txreg_t reg, pend, *regs; 313 1.1 uch int i, j; 314 1.1 uch 315 1.1 uch tc = tx_conf_get_tag(); 316 1.1 uch sc = tc->tc_intrt; 317 1.1 uch /* 318 1.35 kamil * Read register ASAP 319 1.1 uch */ 320 1.9 uch regs = sc->sc_regs; 321 1.9 uch regs[0] = tx_conf_read(tc, TX39_INTRSTATUS6_REG); 322 1.9 uch regs[1] = tx_conf_read(tc, TX39_INTRSTATUS1_REG); 323 1.9 uch regs[2] = tx_conf_read(tc, TX39_INTRSTATUS2_REG); 324 1.9 uch regs[3] = tx_conf_read(tc, TX39_INTRSTATUS3_REG); 325 1.9 uch regs[4] = tx_conf_read(tc, TX39_INTRSTATUS4_REG); 326 1.9 uch regs[5] = tx_conf_read(tc, TX39_INTRSTATUS5_REG); 327 1.1 uch #ifdef TX392X 328 1.9 uch regs[7] = tx_conf_read(tc, TX39_INTRSTATUS7_REG); 329 1.9 uch regs[8] = tx_conf_read(tc, TX39_INTRSTATUS8_REG); 330 1.1 uch #endif 331 1.1 uch 332 1.30 tsutsui while (ppl < (ipl = splintr(&ipending))) { 333 1.16 uch #ifdef TX39ICU_DEBUG 334 1.30 tsutsui if (!(ipending & MIPS_INT_MASK_4) && 335 1.30 tsutsui !(ipending & MIPS_INT_MASK_2)) { 336 1.30 tsutsui dbg_bit_print(ipending); 337 1.30 tsutsui panic("bogus HwInt"); 338 1.30 tsutsui } 339 1.30 tsutsui if (tx39icu_debug > 1) { 340 1.30 tsutsui tx39_intr_dump(sc); 341 1.30 tsutsui } 342 1.16 uch #endif /* TX39ICU_DEBUG */ 343 1.1 uch 344 1.30 tsutsui /* IRQHIGH */ 345 1.30 tsutsui if (ipending & MIPS_INT_MASK_4) { 346 1.30 tsutsui tx39_irqhigh_intr(ipending, pc, status); 347 1.30 tsutsui } 348 1.1 uch 349 1.30 tsutsui /* IRQLOW */ 350 1.30 tsutsui if (ipending & MIPS_INT_MASK_2) { 351 1.30 tsutsui for (i = 1; i <= TX39_INTRSET_MAX; i++) { 352 1.30 tsutsui int ofs; 353 1.1 uch #ifdef TX392X 354 1.30 tsutsui if (i == 6) 355 1.30 tsutsui continue; 356 1.1 uch #endif /* TX392X */ 357 1.30 tsutsui ofs = TX39_INTRSTATUS_REG(i); 358 1.30 tsutsui pend = sc->sc_regs[i]; 359 1.30 tsutsui reg = sc->sc_le_mask[i] & pend; 360 1.30 tsutsui /* Clear interrupts */ 361 1.30 tsutsui tx_conf_write(tc, ofs, reg); 362 1.30 tsutsui /* Dispatch handler */ 363 1.30 tsutsui for (j = 0 ; j < 32; j++) { 364 1.30 tsutsui if ((reg & (1 << j)) && 365 1.30 tsutsui sc->sc_le_fun[i][j]) { 366 1.16 uch #ifdef TX39ICU_DEBUG 367 1.30 tsutsui if (tx39icu_debug > 1) { 368 1.30 tsutsui tx39intrvec = 369 1.30 tsutsui (i << 16) | j; 370 1.30 tsutsui DPRINTF("IRQLOW " 371 1.30 tsutsui "%d:%d\n", i, j); 372 1.30 tsutsui } 373 1.16 uch #endif /* TX39ICU_DEBUG */ 374 1.30 tsutsui (*sc->sc_le_fun[i][j]) 375 1.30 tsutsui (sc->sc_le_arg[i][j]); 376 1.1 uch 377 1.30 tsutsui } 378 1.1 uch } 379 1.16 uch #ifdef TX39ICU_DEBUG_PRINT_PENDING_INTERRUPT 380 1.30 tsutsui pend &= ~reg; 381 1.30 tsutsui if (pend) { 382 1.30 tsutsui printf("%d pending:", i); 383 1.30 tsutsui dbg_bit_print(pend); 384 1.30 tsutsui } 385 1.1 uch #endif 386 1.1 uch 387 1.30 tsutsui } 388 1.1 uch } 389 1.1 uch #ifdef TX39_WATCHDOGTIMER 390 1.30 tsutsui { 391 1.30 tsutsui extern int tx39biu_intr(void *); 392 1.30 tsutsui /* Bus error (If watch dog timer is enabled)*/ 393 1.30 tsutsui if (ipending & MIPS_INT_MASK_1) { 394 1.30 tsutsui tx39biu_intr(0); /* Clear bus error */ 395 1.30 tsutsui } 396 1.6 uch } 397 1.30 tsutsui /* 398 1.35 kamil * Read register again 399 1.30 tsutsui */ 400 1.30 tsutsui regs[0] = tx_conf_read(tc, TX39_INTRSTATUS6_REG); 401 1.30 tsutsui regs[1] = tx_conf_read(tc, TX39_INTRSTATUS1_REG); 402 1.30 tsutsui regs[2] = tx_conf_read(tc, TX39_INTRSTATUS2_REG); 403 1.30 tsutsui regs[3] = tx_conf_read(tc, TX39_INTRSTATUS3_REG); 404 1.30 tsutsui regs[4] = tx_conf_read(tc, TX39_INTRSTATUS4_REG); 405 1.30 tsutsui regs[5] = tx_conf_read(tc, TX39_INTRSTATUS5_REG); 406 1.30 tsutsui #ifdef TX392X 407 1.30 tsutsui regs[7] = tx_conf_read(tc, TX39_INTRSTATUS7_REG); 408 1.30 tsutsui regs[8] = tx_conf_read(tc, TX39_INTRSTATUS8_REG); 409 1.30 tsutsui #endif 410 1.30 tsutsui #endif 411 1.1 uch } 412 1.6 uch #if 0 413 1.6 uch /* reset priority mask */ 414 1.6 uch reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 415 1.6 uch reg = TX39_INTRENABLE6_PRIORITYMASK_SET(reg, 0xffff); 416 1.6 uch tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 417 1.6 uch #endif 418 1.1 uch } 419 1.1 uch 420 1.1 uch int 421 1.12 uch tx39_irqhigh(int set, int bit) 422 1.1 uch { 423 1.1 uch int i, n; 424 1.1 uch 425 1.1 uch n = sizeof irqhigh_list / sizeof (struct irqhigh_list); 426 1.1 uch for (i = 0; i < n; i++) { 427 1.1 uch if (irqhigh_list[i].qh_set == set && 428 1.1 uch irqhigh_list[i].qh_bit == bit) 429 1.12 uch return (irqhigh_list[i].qh_pri); 430 1.1 uch } 431 1.1 uch 432 1.12 uch return (0); 433 1.1 uch } 434 1.1 uch 435 1.1 uch void 436 1.31 tsutsui tx39_irqhigh_intr(uint32_t ipending, vaddr_t pc, uint32_t status) 437 1.1 uch { 438 1.1 uch struct txintr_high_entry *he; 439 1.1 uch struct tx39icu_softc *sc; 440 1.1 uch struct clockframe cf; 441 1.1 uch tx_chipset_tag_t tc; 442 1.1 uch int i, pri, ofs, set; 443 1.1 uch txreg_t he_mask; 444 1.1 uch 445 1.1 uch tc = tx_conf_get_tag(); 446 1.1 uch sc = tc->tc_intrt; 447 1.1 uch pri = TX39_INTRSTATUS6_INTVECT(sc->sc_regs[0]); 448 1.1 uch 449 1.1 uch if (pri == TX39_INTRPRI13_TIMER_PERIODIC) { 450 1.3 uch tx_conf_write(tc, TX39_INTRCLEAR5_REG, 451 1.12 uch TX39_INTRSTATUS5_PERINT); 452 1.1 uch cf.pc = pc; 453 1.1 uch cf.sr = status; 454 1.30 tsutsui cf.intr = (curcpu()->ci_idepth > 1); 455 1.1 uch hardclock(&cf); 456 1.3 uch 457 1.3 uch return; 458 1.1 uch } 459 1.3 uch 460 1.1 uch /* Handle all pending IRQHIGH interrupts */ 461 1.1 uch for (i = pri; i > 0; i--) { 462 1.1 uch TAILQ_FOREACH(he, &sc->sc_he_head[i], he_link) { 463 1.1 uch set = he->he_set; 464 1.1 uch he_mask = he->he_mask; 465 1.1 uch if (he_mask & (sc->sc_regs[set])) { 466 1.1 uch ofs = TX39_INTRSTATUS_REG(set); 467 1.1 uch /* Clear interrupt */ 468 1.1 uch tx_conf_write(tc, ofs, he_mask); 469 1.16 uch #ifdef TX39ICU_DEBUG 470 1.16 uch if (tx39icu_debug > 1) { 471 1.16 uch tx39intrvec = (set << 16) | 472 1.16 uch (ffs(he_mask) - 1); 473 1.16 uch DPRINTF("IRQHIGH: %d:%d\n", 474 1.16 uch set, ffs(he_mask) - 1); 475 1.1 uch } 476 1.16 uch #endif /* TX39ICU_DEBUG */ 477 1.1 uch /* Dispatch handler */ 478 1.1 uch (*he->he_fun)(he->he_arg); 479 1.1 uch } 480 1.1 uch } 481 1.1 uch } 482 1.1 uch } 483 1.1 uch 484 1.1 uch void 485 1.12 uch tx39_intr_decode(int intr, int *set, int *bit) 486 1.1 uch { 487 1.1 uch if (!intr || intr >= (TX39_INTRSET_MAX + 1) * 32 488 1.1 uch #ifdef TX392X 489 1.1 uch || intr == 6 490 1.1 uch #endif /* TX392X */ 491 1.12 uch ) { 492 1.38 andvar panic("tx39icu_decode: bogus interrupt line. %d", intr); 493 1.1 uch } 494 1.1 uch *set = intr / 32; 495 1.1 uch *bit = intr % 32; 496 1.1 uch } 497 1.1 uch 498 1.1 uch void 499 1.12 uch tx39_irqhigh_establish(tx_chipset_tag_t tc, int set, int bit, int pri, 500 1.12 uch int (*ih_fun)(void *), void *ih_arg) 501 1.1 uch { 502 1.1 uch struct tx39icu_softc *sc; 503 1.1 uch struct txintr_high_entry *he; 504 1.1 uch txreg_t reg; 505 1.1 uch 506 1.1 uch sc = tc->tc_intrt; 507 1.1 uch /* 508 1.6 uch * Add new entry to `pri' priority 509 1.1 uch */ 510 1.37 thorpej he = kmem_zalloc(sizeof(*he), KM_SLEEP); 511 1.1 uch he->he_set = set; 512 1.1 uch he->he_mask= (1 << bit); 513 1.1 uch he->he_fun = ih_fun; 514 1.1 uch he->he_arg = ih_arg; 515 1.1 uch TAILQ_INSERT_TAIL(&sc->sc_he_head[pri], he, he_link); 516 1.1 uch /* 517 1.1 uch * Enable interrupt on this priority. 518 1.1 uch */ 519 1.1 uch reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 520 1.1 uch reg = TX39_INTRENABLE6_PRIORITYMASK_SET(reg, (1 << pri)); 521 1.1 uch tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 522 1.1 uch } 523 1.1 uch 524 1.1 uch void 525 1.12 uch tx39_irqhigh_disestablish(tx_chipset_tag_t tc, int set, int bit, int pri) 526 1.1 uch { 527 1.1 uch struct tx39icu_softc *sc; 528 1.1 uch struct txintr_high_entry *he; 529 1.1 uch txreg_t reg; 530 1.1 uch 531 1.1 uch sc = tc->tc_intrt; 532 1.1 uch TAILQ_FOREACH(he, &sc->sc_he_head[pri], he_link) { 533 1.1 uch if (he->he_set == set && he->he_mask == (1 << bit)) { 534 1.1 uch TAILQ_REMOVE(&sc->sc_he_head[pri], he, he_link); 535 1.37 thorpej kmem_free(he, sizeof(*he)); 536 1.1 uch break; 537 1.1 uch } 538 1.1 uch } 539 1.1 uch 540 1.1 uch if (TAILQ_EMPTY(&sc->sc_he_head[pri])) { 541 1.1 uch reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 542 1.1 uch reg &= ~(1 << pri); 543 1.1 uch tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 544 1.1 uch } 545 1.1 uch } 546 1.1 uch 547 1.1 uch 548 1.12 uch void * 549 1.12 uch tx_intr_establish(tx_chipset_tag_t tc, int line, int mode, int level, 550 1.12 uch int (*ih_fun)(void *), void *ih_arg) 551 1.1 uch { 552 1.1 uch struct tx39icu_softc *sc; 553 1.1 uch txreg_t reg; 554 1.1 uch int bit, set, highpri, ofs; 555 1.1 uch 556 1.1 uch sc = tc->tc_intrt; 557 1.1 uch 558 1.1 uch tx39_intr_decode(line, &set, &bit); 559 1.1 uch 560 1.1 uch sc->sc_le_fun[set][bit] = ih_fun; 561 1.1 uch sc->sc_le_arg[set][bit] = ih_arg; 562 1.16 uch DPRINTF("tx_intr_establish: %d:%d", set, bit); 563 1.1 uch 564 1.1 uch if ((highpri = tx39_irqhigh(set, bit))) { 565 1.1 uch tx39_irqhigh_establish(tc, set, bit, highpri, 566 1.12 uch ih_fun, ih_arg); 567 1.16 uch DPRINTF("(high)\n"); 568 1.1 uch } else { 569 1.1 uch /* Set mask for acknowledge. */ 570 1.1 uch sc->sc_le_mask[set] |= (1 << bit); 571 1.1 uch /* Enable interrupt */ 572 1.1 uch ofs = TX39_INTRENABLE_REG(set); 573 1.1 uch reg = tx_conf_read(tc, ofs); 574 1.1 uch reg |= (1 << bit); 575 1.1 uch tx_conf_write(tc, ofs, reg); 576 1.16 uch DPRINTF("(low)\n"); 577 1.1 uch } 578 1.1 uch 579 1.12 uch return ((void *)line); 580 1.1 uch } 581 1.1 uch 582 1.1 uch void 583 1.12 uch tx_intr_disestablish(tx_chipset_tag_t tc, void *arg) 584 1.1 uch { 585 1.1 uch struct tx39icu_softc *sc; 586 1.1 uch int set, bit, highpri, ofs; 587 1.1 uch txreg_t reg; 588 1.1 uch 589 1.1 uch sc = tc->tc_intrt; 590 1.1 uch 591 1.1 uch tx39_intr_decode((int)arg, &set, &bit); 592 1.16 uch DPRINTF("tx_intr_disestablish: %d:%d", set, bit); 593 1.1 uch 594 1.1 uch if ((highpri = tx39_irqhigh(set, bit))) { 595 1.1 uch tx39_irqhigh_disestablish(tc, set, bit, highpri); 596 1.16 uch DPRINTF("(high)\n"); 597 1.1 uch } else { 598 1.1 uch sc->sc_le_fun[set][bit] = 0; 599 1.1 uch sc->sc_le_arg[set][bit] = 0; 600 1.1 uch sc->sc_le_mask[set] &= ~(1 << bit); 601 1.1 uch ofs = TX39_INTRENABLE_REG(set); 602 1.1 uch reg = tx_conf_read(tc, ofs); 603 1.1 uch reg &= ~(1 << bit); 604 1.1 uch tx_conf_write(tc, ofs, reg); 605 1.16 uch DPRINTF("(low)\n"); 606 1.1 uch } 607 1.1 uch } 608 1.1 uch 609 1.30 tsutsui uint32_t 610 1.12 uch tx_intr_status(tx_chipset_tag_t tc, int r) 611 1.1 uch { 612 1.6 uch struct tx39icu_softc *sc = tc->tc_intrt; 613 1.6 uch 614 1.6 uch if (r < 0 || r >= TX39_INTRSET_MAX + 1) 615 1.6 uch panic("tx_intr_status: invalid index %d", r); 616 1.6 uch 617 1.30 tsutsui return (uint32_t)(sc->sc_regs[r]); 618 1.1 uch } 619 1.1 uch 620 1.1 uch #ifdef USE_POLL 621 1.12 uch void * 622 1.12 uch tx39_poll_establish(tx_chipset_tag_t tc, int interval, int level, 623 1.12 uch int (*ih_fun)(void *), void *ih_arg) 624 1.1 uch { 625 1.1 uch struct tx39icu_softc *sc; 626 1.1 uch struct txpoll_entry *p; 627 1.5 uch int s; 628 1.5 uch void *ret; 629 1.5 uch 630 1.37 thorpej p = kmem_zalloc(sizeof(*p), KM_SLEEP); 631 1.1 uch p->p_fun = ih_fun; 632 1.1 uch p->p_arg = ih_arg; 633 1.1 uch p->p_cnt = interval; 634 1.5 uch 635 1.36 chs s = splhigh(); 636 1.36 chs sc = tc->tc_intrt; 637 1.36 chs 638 1.1 uch if (!sc->sc_polling) { 639 1.5 uch tx39clock_alarm_set(tc, 33); /* 33 msec */ 640 1.5 uch 641 1.34 christos if (!(sc->sc_poll_ih = tx_intr_establish( 642 1.34 christos tc, MAKEINTR(5, TX39_INTRSTATUS5_ALARMINT), 643 1.34 christos IST_EDGE, level, tx39_poll_intr, sc))) { 644 1.1 uch printf("tx39_poll_establish: can't hook\n"); 645 1.5 uch 646 1.5 uch splx(s); 647 1.37 thorpej kmem_free(p, sizeof(*p)); 648 1.12 uch return (0); 649 1.1 uch } 650 1.1 uch } 651 1.5 uch 652 1.1 uch sc->sc_polling++; 653 1.1 uch p->p_desc = sc->sc_polling; 654 1.1 uch TAILQ_INSERT_TAIL(&sc->sc_p_head, p, p_link); 655 1.12 uch ret = (void *)p->p_desc; 656 1.1 uch 657 1.5 uch splx(s); 658 1.12 uch return (ret); 659 1.1 uch } 660 1.1 uch 661 1.1 uch void 662 1.12 uch tx39_poll_disestablish(tx_chipset_tag_t tc, void *arg) 663 1.1 uch { 664 1.1 uch struct tx39icu_softc *sc; 665 1.1 uch struct txpoll_entry *p; 666 1.5 uch int s, desc; 667 1.5 uch 668 1.5 uch s = splhigh(); 669 1.1 uch sc = tc->tc_intrt; 670 1.1 uch 671 1.1 uch desc = (int)arg; 672 1.1 uch TAILQ_FOREACH(p, &sc->sc_p_head, p_link) { 673 1.1 uch if (p->p_desc == desc) { 674 1.1 uch TAILQ_REMOVE(&sc->sc_p_head, p, p_link); 675 1.37 thorpej kmem_free(p, sizeof(*p)); 676 1.1 uch break; 677 1.1 uch } 678 1.1 uch } 679 1.5 uch 680 1.1 uch if (TAILQ_EMPTY(&sc->sc_p_head)) { 681 1.1 uch sc->sc_polling = 0; 682 1.1 uch tx_intr_disestablish(tc, sc->sc_poll_ih); 683 1.1 uch } 684 1.5 uch 685 1.5 uch splx(s); 686 1.5 uch return; 687 1.1 uch } 688 1.1 uch 689 1.1 uch int 690 1.12 uch tx39_poll_intr(void *arg) 691 1.1 uch { 692 1.1 uch struct tx39icu_softc *sc = arg; 693 1.1 uch struct txpoll_entry *p; 694 1.1 uch 695 1.5 uch tx39clock_alarm_refill(sc->sc_tc); 696 1.5 uch 697 1.1 uch if (!sc->sc_polling) { 698 1.12 uch return (0); 699 1.1 uch } 700 1.1 uch sc->sc_pollcnt++; 701 1.1 uch TAILQ_FOREACH(p, &sc->sc_p_head, p_link) { 702 1.1 uch if (sc->sc_pollcnt % p->p_cnt == 0) { 703 1.5 uch if ((*p->p_fun)(p->p_arg) == POLL_END) 704 1.5 uch goto disestablish; 705 1.1 uch } 706 1.1 uch } 707 1.5 uch 708 1.12 uch return (0); 709 1.5 uch 710 1.5 uch disestablish: 711 1.5 uch TAILQ_REMOVE(&sc->sc_p_head, p, p_link); 712 1.37 thorpej kmem_free(p, sizeof(*p)); 713 1.5 uch if (TAILQ_EMPTY(&sc->sc_p_head)) { 714 1.5 uch sc->sc_polling = 0; 715 1.5 uch tx_intr_disestablish(sc->sc_tc, sc->sc_poll_ih); 716 1.5 uch } 717 1.5 uch 718 1.12 uch return (0); 719 1.1 uch } 720 1.1 uch #endif /* USE_POLL */ 721 1.6 uch 722 1.6 uch void 723 1.12 uch tx39_intr_dump(struct tx39icu_softc *sc) 724 1.6 uch { 725 1.6 uch tx_chipset_tag_t tc = sc->sc_tc; 726 1.6 uch int i, j, ofs; 727 1.6 uch txreg_t reg; 728 1.6 uch char msg[16]; 729 1.6 uch 730 1.6 uch for (i = 1; i <= TX39_INTRSET_MAX; i++) { 731 1.6 uch #ifdef TX392X 732 1.6 uch if (i == 6) 733 1.6 uch continue; 734 1.6 uch #endif /* TX392X */ 735 1.6 uch for (reg = j = 0; j < 32; j++) { 736 1.6 uch if (tx39_irqhigh(i, j)) { 737 1.6 uch reg |= (1 << j); 738 1.6 uch } 739 1.6 uch } 740 1.33 christos snprintf(msg, sizeof(msg), "%d high", i); 741 1.17 takemura dbg_bit_print_msg(reg, msg); 742 1.33 christos snprintf(msg, sizeof(msg), "%d status", i); 743 1.17 takemura dbg_bit_print_msg(sc->sc_regs[i], msg); 744 1.6 uch ofs = TX39_INTRENABLE_REG(i); 745 1.6 uch reg = tx_conf_read(tc, ofs); 746 1.33 christos snprintf(msg, sizeof(msg), "%d enable", i); 747 1.17 takemura dbg_bit_print_msg(reg, msg); 748 1.6 uch } 749 1.6 uch reg = sc->sc_regs[0]; 750 1.6 uch printf("<%s><%s> vector=%2d\t\t[6 status]\n", 751 1.12 uch reg & TX39_INTRSTATUS6_IRQHIGH ? "HI" : "--", 752 1.12 uch reg & TX39_INTRSTATUS6_IRQLOW ? "LO" : "--", 753 1.12 uch TX39_INTRSTATUS6_INTVECT(reg)); 754 1.6 uch reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 755 1.17 takemura __dbg_bit_print(reg, sizeof(reg), 0, 18, "6 enable", 756 1.17 takemura DBG_BIT_PRINT_COUNT); 757 1.6 uch 758 1.6 uch } 759