1 1.8 jmcneill /* $NetBSD: yeeloong_machdep.c,v 1.8 2016/07/10 00:14:36 jmcneill Exp $ */ 2 1.1 bouyer /* $OpenBSD: yeeloong_machdep.c,v 1.16 2011/04/15 20:40:06 deraadt Exp $ */ 3 1.1 bouyer 4 1.1 bouyer /* 5 1.1 bouyer * Copyright (c) 2009, 2010 Miodrag Vallat. 6 1.1 bouyer * 7 1.1 bouyer * Permission to use, copy, modify, and distribute this software for any 8 1.1 bouyer * purpose with or without fee is hereby granted, provided that the above 9 1.1 bouyer * copyright notice and this permission notice appear in all copies. 10 1.1 bouyer * 11 1.1 bouyer * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 1.1 bouyer * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 1.1 bouyer * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 1.1 bouyer * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 1.1 bouyer * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 1.1 bouyer * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 1.1 bouyer * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 1.1 bouyer */ 19 1.1 bouyer 20 1.1 bouyer /* 21 1.1 bouyer * Lemote {Fu,Lyn,Yee}loong specific code and configuration data. 22 1.1 bouyer * (this file really ought to be named lemote_machdep.c by now) 23 1.1 bouyer */ 24 1.1 bouyer 25 1.3 nonaka #include <sys/cdefs.h> 26 1.8 jmcneill __KERNEL_RCSID(0, "$NetBSD: yeeloong_machdep.c,v 1.8 2016/07/10 00:14:36 jmcneill Exp $"); 27 1.3 nonaka 28 1.1 bouyer #include <sys/param.h> 29 1.1 bouyer #include <sys/systm.h> 30 1.1 bouyer #include <sys/device.h> 31 1.1 bouyer #include <sys/types.h> 32 1.1 bouyer 33 1.7 macallan #include <mips/cpuregs.h> 34 1.1 bouyer #include <evbmips/loongson/autoconf.h> 35 1.1 bouyer #include <mips/pmon/pmon.h> 36 1.1 bouyer #include <evbmips/loongson/loongson_intr.h> 37 1.1 bouyer #include <evbmips/loongson/loongson_bus_defs.h> 38 1.1 bouyer #include <evbmips/loongson/loongson_isa.h> 39 1.1 bouyer 40 1.1 bouyer #include <dev/isa/isareg.h> 41 1.1 bouyer #include <dev/isa/isavar.h> 42 1.1 bouyer #include <dev/ic/i8259reg.h> 43 1.1 bouyer 44 1.1 bouyer #include <dev/pci/pcireg.h> 45 1.1 bouyer #include <dev/pci/pcivar.h> 46 1.1 bouyer #include <dev/pci/pcidevs.h> 47 1.1 bouyer 48 1.1 bouyer #include <mips/bonito/bonitoreg.h> 49 1.1 bouyer #include <mips/bonito/bonitovar.h> 50 1.1 bouyer 51 1.1 bouyer #include <evbmips/loongson/dev/kb3310var.h> 52 1.1 bouyer #include <evbmips/loongson/dev/glxreg.h> 53 1.1 bouyer #include <evbmips/loongson/dev/glxvar.h> 54 1.1 bouyer 55 1.1 bouyer #include "com.h" 56 1.1 bouyer #include "isa.h" 57 1.1 bouyer #include "ykbec.h" 58 1.1 bouyer 59 1.1 bouyer #if NCOM > 0 60 1.1 bouyer #include <sys/termios.h> 61 1.1 bouyer #include <dev/ic/comvar.h> 62 1.1 bouyer #endif 63 1.1 bouyer 64 1.1 bouyer #ifdef LOW_DEBUG 65 1.1 bouyer #define DPRINTF(x) printf x 66 1.1 bouyer #else 67 1.1 bouyer #define DPRINTF(x) 68 1.1 bouyer #endif 69 1.1 bouyer 70 1.4 chs void lemote_device_register(device_t, void *); 71 1.1 bouyer void lemote_reset(void); 72 1.1 bouyer 73 1.1 bouyer void fuloong_powerdown(void); 74 1.1 bouyer void fuloong_setup(void); 75 1.1 bouyer 76 1.1 bouyer void yeeloong_powerdown(void); 77 1.1 bouyer 78 1.1 bouyer void lemote_pci_attach_hook(device_t, device_t, 79 1.1 bouyer struct pcibus_attach_args *); 80 1.1 bouyer int lemote_intr_map(int, int, int, pci_intr_handle_t *); 81 1.1 bouyer 82 1.4 chs void lemote_isa_attach_hook(device_t, device_t, 83 1.1 bouyer struct isabus_attach_args *); 84 1.1 bouyer void *lemote_isa_intr_establish(void *, int, int, int, 85 1.1 bouyer int (*)(void *), void *); 86 1.1 bouyer void lemote_isa_intr_disestablish(void *, void *); 87 1.1 bouyer const struct evcnt * lemote_isa_intr_evcnt(void *, int); 88 1.6 christos const char * lemote_isa_intr_string(void *, int, char *, size_t); 89 1.1 bouyer 90 1.1 bouyer uint lemote_get_isa_imr(void); 91 1.1 bouyer uint lemote_get_isa_isr(void); 92 1.1 bouyer void lemote_isa_intr(int, vaddr_t, uint32_t); 93 1.1 bouyer 94 1.1 bouyer const struct bonito_config lemote_bonito = { 95 1.1 bouyer .bc_adbase = 11, 96 1.1 bouyer 97 1.1 bouyer .bc_gpioIE = LOONGSON_INTRMASK_GPIO, 98 1.1 bouyer .bc_intEdge = LOONGSON_INTRMASK_PCI_SYSERR | 99 1.1 bouyer LOONGSON_INTRMASK_PCI_PARERR, 100 1.1 bouyer .bc_intSteer = 0, 101 1.1 bouyer .bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR | 102 1.1 bouyer LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR | 103 1.1 bouyer LOONGSON_INTRMASK_INT0 | LOONGSON_INTRMASK_INT1, 104 1.1 bouyer 105 1.1 bouyer .bc_attach_hook = lemote_pci_attach_hook, 106 1.1 bouyer }; 107 1.1 bouyer 108 1.1 bouyer const struct legacy_io_range fuloong_legacy_ranges[] = { 109 1.1 bouyer /* isa */ 110 1.1 bouyer { IO_DMAPG + 4, IO_DMAPG + 4 }, 111 1.1 bouyer /* mcclock */ 112 1.1 bouyer { IO_RTC, IO_RTC + 1 }, 113 1.1 bouyer /* pciide */ 114 1.1 bouyer { 0x170, 0x170 + 7 }, 115 1.1 bouyer { 0x1f0, 0x1f0 + 7 }, 116 1.1 bouyer { 0x376, 0x376 }, 117 1.1 bouyer { 0x3f6, 0x3f6 }, 118 1.1 bouyer /* com */ 119 1.1 bouyer { IO_COM1, IO_COM1 + 8 }, /* IR port */ 120 1.1 bouyer { IO_COM2, IO_COM2 + 8 }, /* serial port */ 121 1.1 bouyer 122 1.1 bouyer { 0 } 123 1.1 bouyer }; 124 1.1 bouyer 125 1.1 bouyer const struct legacy_io_range lynloong_legacy_ranges[] = { 126 1.1 bouyer /* isa */ 127 1.1 bouyer { IO_DMAPG + 4, IO_DMAPG + 4 }, 128 1.1 bouyer /* mcclock */ 129 1.1 bouyer { IO_RTC, IO_RTC + 1 }, 130 1.1 bouyer /* pciide */ 131 1.1 bouyer { 0x170, 0x170 + 7 }, 132 1.1 bouyer { 0x1f0, 0x1f0 + 7 }, 133 1.1 bouyer { 0x376, 0x376 }, 134 1.1 bouyer { 0x3f6, 0x3f6 }, 135 1.1 bouyer #if 0 /* no external connector */ 136 1.1 bouyer /* com */ 137 1.1 bouyer { IO_COM2, IO_COM2 + 8 }, 138 1.1 bouyer #endif 139 1.1 bouyer 140 1.1 bouyer { 0 } 141 1.1 bouyer }; 142 1.1 bouyer 143 1.1 bouyer const struct legacy_io_range yeeloong_legacy_ranges[] = { 144 1.1 bouyer /* isa */ 145 1.1 bouyer { IO_DMAPG + 4, IO_DMAPG + 4 }, 146 1.1 bouyer /* pckbc */ 147 1.1 bouyer { IO_KBD, IO_KBD }, 148 1.1 bouyer { IO_KBD + 4, IO_KBD + 4 }, 149 1.1 bouyer /* mcclock */ 150 1.1 bouyer { IO_RTC, IO_RTC + 1 }, 151 1.1 bouyer /* pciide */ 152 1.1 bouyer { 0x170, 0x170 + 7 }, 153 1.1 bouyer { 0x1f0, 0x1f0 + 7 }, 154 1.1 bouyer { 0x376, 0x376 }, 155 1.1 bouyer { 0x3f6, 0x3f6 }, 156 1.1 bouyer /* kb3110b embedded controller */ 157 1.1 bouyer { 0x381, 0x383 }, 158 1.1 bouyer 159 1.1 bouyer { 0 } 160 1.1 bouyer }; 161 1.1 bouyer 162 1.1 bouyer struct mips_isa_chipset lemote_isa_chipset = { 163 1.1 bouyer .ic_v = NULL, 164 1.1 bouyer 165 1.1 bouyer .ic_attach_hook = lemote_isa_attach_hook, 166 1.1 bouyer .ic_intr_establish = lemote_isa_intr_establish, 167 1.1 bouyer .ic_intr_disestablish = lemote_isa_intr_disestablish, 168 1.1 bouyer .ic_intr_evcnt = lemote_isa_intr_evcnt, 169 1.1 bouyer .ic_intr_string = lemote_isa_intr_string, 170 1.1 bouyer }; 171 1.1 bouyer 172 1.1 bouyer const struct platform fuloong_platform = { 173 1.1 bouyer .system_type = LOONGSON_FULOONG, 174 1.1 bouyer .vendor = "Lemote", 175 1.1 bouyer .product = "Fuloong", 176 1.1 bouyer 177 1.1 bouyer .bonito_config = &lemote_bonito, 178 1.1 bouyer .isa_chipset = &lemote_isa_chipset, 179 1.1 bouyer .legacy_io_ranges = fuloong_legacy_ranges, 180 1.1 bouyer .bonito_mips_intr = MIPS_INT_MASK_4, 181 1.1 bouyer .isa_mips_intr = MIPS_INT_MASK_0, 182 1.1 bouyer .isa_intr = lemote_isa_intr, 183 1.1 bouyer .p_pci_intr_map = lemote_intr_map, 184 1.1 bouyer .irq_map =loongson2f_irqmap, 185 1.1 bouyer 186 1.1 bouyer .setup = fuloong_setup, 187 1.1 bouyer .device_register = lemote_device_register, 188 1.1 bouyer 189 1.1 bouyer .powerdown = fuloong_powerdown, 190 1.1 bouyer .reset = lemote_reset 191 1.1 bouyer }; 192 1.1 bouyer 193 1.1 bouyer const struct platform lynloong_platform = { 194 1.1 bouyer .system_type = LOONGSON_LYNLOONG, 195 1.1 bouyer .vendor = "Lemote", 196 1.1 bouyer .product = "Lynloong", 197 1.1 bouyer 198 1.1 bouyer .bonito_config = &lemote_bonito, 199 1.1 bouyer .isa_chipset = &lemote_isa_chipset, 200 1.1 bouyer .legacy_io_ranges = lynloong_legacy_ranges, 201 1.1 bouyer .bonito_mips_intr = MIPS_INT_MASK_4, 202 1.1 bouyer .isa_mips_intr = MIPS_INT_MASK_0, 203 1.1 bouyer .isa_intr = lemote_isa_intr, 204 1.1 bouyer .p_pci_intr_map = lemote_intr_map, 205 1.1 bouyer .irq_map =loongson2f_irqmap, 206 1.1 bouyer 207 1.1 bouyer .setup = fuloong_setup, 208 1.1 bouyer .device_register = lemote_device_register, 209 1.1 bouyer 210 1.1 bouyer .powerdown = fuloong_powerdown, 211 1.1 bouyer .reset = lemote_reset 212 1.1 bouyer }; 213 1.1 bouyer 214 1.1 bouyer const struct platform yeeloong_platform = { 215 1.1 bouyer .system_type = LOONGSON_YEELOONG, 216 1.1 bouyer .vendor = "Lemote", 217 1.1 bouyer .product = "Yeeloong", 218 1.1 bouyer 219 1.1 bouyer .bonito_config = &lemote_bonito, 220 1.1 bouyer .isa_chipset = &lemote_isa_chipset, 221 1.1 bouyer .legacy_io_ranges = yeeloong_legacy_ranges, 222 1.1 bouyer .bonito_mips_intr = MIPS_INT_MASK_4, 223 1.1 bouyer .isa_mips_intr = MIPS_INT_MASK_0, 224 1.1 bouyer .isa_intr = lemote_isa_intr, 225 1.1 bouyer .p_pci_intr_map = lemote_intr_map, 226 1.1 bouyer .irq_map =loongson2f_irqmap, 227 1.1 bouyer 228 1.1 bouyer .setup = NULL, 229 1.1 bouyer .device_register = lemote_device_register, 230 1.1 bouyer 231 1.1 bouyer .powerdown = yeeloong_powerdown, 232 1.1 bouyer .reset = lemote_reset, 233 1.1 bouyer #if NYKBEC > 0 234 1.1 bouyer .suspend = ykbec_suspend, 235 1.1 bouyer .resume = ykbec_resume 236 1.1 bouyer #endif 237 1.1 bouyer }; 238 1.1 bouyer 239 1.5 macallan #if NISA > 0 240 1.1 bouyer static int stray_intr[BONITO_NISA]; 241 1.5 macallan #endif 242 1.1 bouyer /* 243 1.1 bouyer * PCI model specific routines 244 1.1 bouyer */ 245 1.1 bouyer 246 1.1 bouyer void 247 1.1 bouyer lemote_pci_attach_hook(device_t parent, device_t self, 248 1.1 bouyer struct pcibus_attach_args *pba) 249 1.1 bouyer { 250 1.1 bouyer pci_chipset_tag_t pc = pba->pba_pc; 251 1.3 nonaka pcitag_t tag; 252 1.1 bouyer pcireg_t id; 253 1.1 bouyer int dev, i; 254 1.1 bouyer 255 1.1 bouyer if (pba->pba_bus != 0) 256 1.1 bouyer return; 257 1.1 bouyer 258 1.1 bouyer /* 259 1.1 bouyer * Check for an AMD CS5536 chip; if one is found, register 260 1.1 bouyer * the proper PCI configuration space hooks. 261 1.1 bouyer */ 262 1.1 bouyer 263 1.1 bouyer for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) { 264 1.1 bouyer tag = pci_make_tag(pc, 0, dev, 0); 265 1.1 bouyer id = pci_conf_read(pc, tag, PCI_ID_REG); 266 1.1 bouyer DPRINTF(("lemote_pci_attach_hook id 0x%x\n", id)); 267 1.1 bouyer if (id == PCI_ID_CODE(PCI_VENDOR_AMD, 268 1.1 bouyer PCI_PRODUCT_AMD_CS5536_PCISB)) { 269 1.1 bouyer glx_init(pc, tag, dev); 270 1.1 bouyer break; 271 1.1 bouyer } 272 1.1 bouyer } 273 1.3 nonaka 274 1.1 bouyer wrmsr(GCSC_PIC_SHDW, 0); 275 1.1 bouyer DPRINTF(("PMON setup picregs:")); 276 1.1 bouyer for (i = 0; i < 12; i++) { 277 1.1 bouyer if (i == 6) 278 1.1 bouyer DPRINTF((" | ")); 279 1.1 bouyer DPRINTF((" 0x%x", (uint32_t)(rdmsr(GCSC_PIC_SHDW) & 0xff))); 280 1.1 bouyer } 281 1.1 bouyer DPRINTF(("\n")); 282 1.1 bouyer DPRINTF(("intsel 0x%x 0x%x\n", REGVAL8(BONITO_PCIIO_BASE + 0x4d0), 283 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + 0x4d1))); 284 1.3 nonaka 285 1.1 bouyer /* setup legacy interrupt controller */ 286 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1) = 0xff; 287 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW1) = 288 1.1 bouyer ICW1_SELECT | ICW1_IC4; 289 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW2) = ICW2_VECTOR(0); 290 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW3) = ICW3_CASCADE(2); 291 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW4) = ICW4_8086; 292 1.1 bouyer delay(100); 293 1.1 bouyer /* mask all interrupts */ 294 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1) = 0xff; 295 1.1 bouyer 296 1.1 bouyer /* read ISR by default. */ 297 1.3 nonaka REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = OCW3_SELECT | OCW3_RR; 298 1.1 bouyer (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3); 299 1.1 bouyer 300 1.1 bouyer /* reset; program device, four bytes */ 301 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1) = 0xff; 302 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW1) = 303 1.1 bouyer ICW1_SELECT | ICW1_IC4; 304 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW2) = ICW2_VECTOR(8); 305 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW3) = ICW3_SIC(2); 306 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW4) = ICW4_8086; 307 1.1 bouyer delay(100); 308 1.1 bouyer /* leave interrupts masked */ 309 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1) = 0xff; 310 1.1 bouyer /* read ISR by default. */ 311 1.3 nonaka REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = OCW3_SELECT | OCW3_RR; 312 1.1 bouyer (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3); 313 1.1 bouyer } 314 1.1 bouyer 315 1.1 bouyer int 316 1.1 bouyer lemote_intr_map(int dev, int fn, int pin, pci_intr_handle_t *ihp) 317 1.1 bouyer { 318 1.1 bouyer switch (dev) { 319 1.1 bouyer /* onboard devices, only pin A is wired */ 320 1.1 bouyer case 6: 321 1.1 bouyer case 7: 322 1.1 bouyer case 8: 323 1.1 bouyer case 9: 324 1.1 bouyer if (pin == PCI_INTERRUPT_PIN_A) { 325 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + 326 1.1 bouyer (dev - 6)); 327 1.3 nonaka return (0); 328 1.1 bouyer } 329 1.1 bouyer break; 330 1.1 bouyer /* PCI slot */ 331 1.1 bouyer case 10: 332 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + 333 1.1 bouyer (pin - PCI_INTERRUPT_PIN_A)); 334 1.3 nonaka return (0); 335 1.1 bouyer /* Geode chip */ 336 1.1 bouyer case 14: 337 1.1 bouyer switch (fn) { 338 1.1 bouyer case 1: /* Flash */ 339 1.1 bouyer *ihp = BONITO_ISA_IRQ(6); 340 1.3 nonaka return (0); 341 1.1 bouyer case 3: /* AC97 */ 342 1.1 bouyer *ihp = BONITO_ISA_IRQ(9); 343 1.3 nonaka return (0); 344 1.1 bouyer case 4: /* OHCI */ 345 1.1 bouyer case 5: /* EHCI */ 346 1.1 bouyer *ihp = BONITO_ISA_IRQ(11); 347 1.3 nonaka return (0); 348 1.1 bouyer } 349 1.1 bouyer break; 350 1.1 bouyer default: 351 1.1 bouyer break; 352 1.1 bouyer } 353 1.3 nonaka return (1); 354 1.1 bouyer } 355 1.1 bouyer 356 1.1 bouyer /* 357 1.1 bouyer * ISA model specific routines 358 1.1 bouyer */ 359 1.5 macallan #if NISA > 0 360 1.1 bouyer void 361 1.4 chs lemote_isa_attach_hook(device_t parent, device_t self, 362 1.1 bouyer struct isabus_attach_args *iba) 363 1.1 bouyer { 364 1.3 nonaka 365 1.1 bouyer loongson_set_isa_imr(loongson_isaimr); 366 1.1 bouyer } 367 1.1 bouyer 368 1.1 bouyer void * 369 1.1 bouyer lemote_isa_intr_establish(void *v, int irq, int type, int level, 370 1.1 bouyer int (*handler)(void *), void *arg) 371 1.1 bouyer { 372 1.1 bouyer void *ih; 373 1.1 bouyer uint imr; 374 1.1 bouyer 375 1.1 bouyer ih = evbmips_intr_establish(BONITO_ISA_IRQ(irq), handler, arg); 376 1.1 bouyer if (ih == NULL) 377 1.3 nonaka return (NULL); 378 1.3 nonaka 379 1.1 bouyer /* enable interrupt */ 380 1.1 bouyer imr = lemote_get_isa_imr(); 381 1.1 bouyer imr |= (1 << irq); 382 1.3 nonaka DPRINTF(("lemote_isa_intr_establish: enable irq %d 0x%x\n", irq, imr)); 383 1.1 bouyer loongson_set_isa_imr(imr); 384 1.3 nonaka return (ih); 385 1.1 bouyer } 386 1.1 bouyer 387 1.1 bouyer void 388 1.1 bouyer lemote_isa_intr_disestablish(void *v, void *ih) 389 1.1 bouyer { 390 1.3 nonaka 391 1.1 bouyer evbmips_intr_disestablish(ih); 392 1.1 bouyer } 393 1.1 bouyer 394 1.1 bouyer const struct evcnt * 395 1.1 bouyer lemote_isa_intr_evcnt(void *v, int irq) 396 1.1 bouyer { 397 1.1 bouyer 398 1.1 bouyer if (irq == 0 || irq >= BONITO_NISA || irq == 2) 399 1.1 bouyer panic("lemote_isa_intr_evcnt: bogus isa irq 0x%x", irq); 400 1.1 bouyer 401 1.1 bouyer return (&bonito_intrhead[BONITO_ISA_IRQ(irq)].intr_count); 402 1.1 bouyer } 403 1.1 bouyer 404 1.1 bouyer const char * 405 1.6 christos lemote_isa_intr_string(void *v, int irq, char *buf, size_t len) 406 1.1 bouyer { 407 1.1 bouyer if (irq == 0 || irq >= BONITO_NISA || irq == 2) 408 1.1 bouyer panic("lemote_isa_intr_string: bogus isa irq 0x%x", irq); 409 1.1 bouyer 410 1.6 christos return loongson_intr_string(&lemote_bonito, BONITO_ISA_IRQ(irq), buf, 411 1.6 christos len); 412 1.1 bouyer } 413 1.5 macallan #endif 414 1.1 bouyer /* 415 1.1 bouyer * Legacy (ISA) interrupt handling 416 1.1 bouyer */ 417 1.1 bouyer 418 1.1 bouyer /* 419 1.1 bouyer * Process legacy interrupts. 420 1.1 bouyer * 421 1.1 bouyer * XXX On 2F, ISA interrupts only occur on LOONGSON_INTR_INT0, but since 422 1.1 bouyer * XXX the other LOONGSON_INTR_INT# are unmaskable, bad things will happen 423 1.1 bouyer * XXX if they ever are triggered... 424 1.1 bouyer */ 425 1.1 bouyer void 426 1.1 bouyer lemote_isa_intr(int ipl, vaddr_t pc, uint32_t ipending) 427 1.1 bouyer { 428 1.1 bouyer #if NISA > 0 429 1.3 nonaka struct evbmips_intrhand *ih; 430 1.1 bouyer uint32_t isr, imr, mask; 431 1.3 nonaka int bitno; 432 1.1 bouyer int rc; 433 1.1 bouyer 434 1.1 bouyer imr = lemote_get_isa_imr(); 435 1.1 bouyer isr = lemote_get_isa_isr() & imr; 436 1.3 nonaka if (isr == 0) 437 1.3 nonaka return; 438 1.1 bouyer 439 1.1 bouyer /* 440 1.1 bouyer * Now process allowed interrupts. 441 1.1 bouyer */ 442 1.3 nonaka /* Service higher level interrupts first */ 443 1.3 nonaka for (bitno = BONITO_NISA - 1, mask = 1UL << bitno; 444 1.3 nonaka mask != 0; 445 1.3 nonaka bitno--, mask >>= 1) { 446 1.3 nonaka if ((isr & mask) == 0) 447 1.3 nonaka continue; 448 1.3 nonaka 449 1.3 nonaka loongson_isa_specific_eoi(bitno); 450 1.3 nonaka 451 1.3 nonaka rc = 0; 452 1.3 nonaka LIST_FOREACH(ih, 453 1.3 nonaka &bonito_intrhead[BONITO_ISA_IRQ(bitno)].intrhand_head, 454 1.3 nonaka ih_q) { 455 1.3 nonaka if ((*ih->ih_func)(ih->ih_arg) != 0) { 456 1.3 nonaka rc = 1; 457 1.3 nonaka bonito_intrhead[BONITO_ISA_IRQ(bitno)].intr_count.ev_count++; 458 1.1 bouyer } 459 1.3 nonaka } 460 1.3 nonaka if (rc == 0) { 461 1.3 nonaka if (stray_intr[bitno]++ & 0x10000) { 462 1.3 nonaka printf("spurious isa interrupt %d\n", bitno); 463 1.3 nonaka stray_intr[bitno] = 0; 464 1.1 bouyer } 465 1.1 bouyer } 466 1.1 bouyer 467 1.3 nonaka if ((isr ^= mask) == 0) 468 1.3 nonaka break; 469 1.1 bouyer } 470 1.1 bouyer 471 1.3 nonaka /* 472 1.3 nonaka * Reenable interrupts which have been serviced. 473 1.3 nonaka */ 474 1.3 nonaka loongson_set_isa_imr(imr); 475 1.1 bouyer #endif 476 1.1 bouyer } 477 1.1 bouyer 478 1.1 bouyer uint 479 1.2 christos lemote_get_isa_imr(void) 480 1.1 bouyer { 481 1.1 bouyer uint imr1, imr2; 482 1.1 bouyer 483 1.3 nonaka imr1 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1); 484 1.1 bouyer imr1 &= ~(1 << 2); /* hide cascade */ 485 1.3 nonaka imr2 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1); 486 1.1 bouyer 487 1.3 nonaka return ((imr2 << 8) | imr1); 488 1.1 bouyer } 489 1.1 bouyer 490 1.1 bouyer uint 491 1.2 christos lemote_get_isa_isr(void) 492 1.1 bouyer { 493 1.3 nonaka uint isr1, isr2; 494 1.1 bouyer 495 1.1 bouyer isr1 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU1); 496 1.3 nonaka isr1 &= ~(1 << 2); 497 1.1 bouyer isr2 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU2); 498 1.1 bouyer 499 1.3 nonaka return ((isr2 << 8) | isr1); 500 1.1 bouyer } 501 1.1 bouyer 502 1.1 bouyer /* 503 1.1 bouyer * Other model specific routines 504 1.1 bouyer */ 505 1.1 bouyer 506 1.1 bouyer void 507 1.2 christos fuloong_powerdown(void) 508 1.1 bouyer { 509 1.1 bouyer vaddr_t gpiobase; 510 1.1 bouyer 511 1.1 bouyer gpiobase = BONITO_PCIIO_BASE + (rdmsr(GCSC_DIVIL_LBAR_GPIO) & 0xff00); 512 1.1 bouyer /* enable GPIO 13 */ 513 1.1 bouyer REGVAL(gpiobase + GCSC_GPIOL_OUT_EN) = GCSC_GPIO_ATOMIC_VALUE(13, 1); 514 1.1 bouyer /* set GPIO13 value to zero */ 515 1.1 bouyer REGVAL(gpiobase + GCSC_GPIOL_OUT_VAL) = GCSC_GPIO_ATOMIC_VALUE(13, 0); 516 1.1 bouyer } 517 1.1 bouyer 518 1.1 bouyer void 519 1.2 christos yeeloong_powerdown(void) 520 1.1 bouyer { 521 1.3 nonaka 522 1.1 bouyer REGVAL(BONITO_GPIODATA) &= ~0x00000001; 523 1.1 bouyer REGVAL(BONITO_GPIOIE) &= ~0x00000001; 524 1.1 bouyer } 525 1.1 bouyer 526 1.1 bouyer void 527 1.2 christos lemote_reset(void) 528 1.1 bouyer { 529 1.3 nonaka 530 1.1 bouyer wrmsr(GCSC_GLCP_SYS_RST, rdmsr(GCSC_GLCP_SYS_RST) | 1); 531 1.1 bouyer } 532 1.1 bouyer 533 1.1 bouyer void 534 1.1 bouyer fuloong_setup(void) 535 1.1 bouyer { 536 1.1 bouyer #if NCOM > 0 537 1.1 bouyer const char *envvar; 538 1.1 bouyer int serial; 539 1.1 bouyer 540 1.1 bouyer envvar = pmon_getenv("nokbd"); 541 1.1 bouyer serial = envvar != NULL; 542 1.1 bouyer envvar = pmon_getenv("novga"); 543 1.1 bouyer serial = serial && envvar != NULL; 544 1.1 bouyer 545 1.1 bouyer //serial = 1; /* XXXXXX */ 546 1.1 bouyer if (serial) { 547 1.1 bouyer comconsiot = &bonito_iot; 548 1.1 bouyer comconsaddr = 0x2f8; 549 1.1 bouyer comconsrate = 115200; /* default PMON console speed */ 550 1.1 bouyer } 551 1.1 bouyer #endif 552 1.1 bouyer } 553 1.1 bouyer 554 1.1 bouyer void 555 1.4 chs lemote_device_register(device_t dev, void *aux) 556 1.1 bouyer { 557 1.1 bouyer const char *name = device_xname(dev); 558 1.1 bouyer 559 1.4 chs if (device_class(dev) != bootdev_class) 560 1.4 chs return; 561 1.1 bouyer 562 1.8 jmcneill /* OHCI memory space access may not be enabled by the BIOS */ 563 1.8 jmcneill if (device_is_a(dev, "ohci")) { 564 1.8 jmcneill struct pci_attach_args *pa = aux; 565 1.8 jmcneill pcireg_t csr = pci_conf_read(pa->pa_pc, pa->pa_tag, 566 1.8 jmcneill PCI_COMMAND_STATUS_REG); 567 1.8 jmcneill if ((csr & PCI_COMMAND_MEM_ENABLE) == 0) { 568 1.8 jmcneill csr |= PCI_COMMAND_MEM_ENABLE; 569 1.8 jmcneill pci_conf_write(pa->pa_pc, pa->pa_tag, 570 1.8 jmcneill PCI_COMMAND_STATUS_REG, csr); 571 1.8 jmcneill } 572 1.8 jmcneill } 573 1.8 jmcneill 574 1.1 bouyer /* 575 1.1 bouyer * The device numbering must match. There's no way 576 1.1 bouyer * pmon tells us more info. Depending on the usb slot 577 1.1 bouyer * and hubs used you may be lucky. Also, assume umass/sd for usb 578 1.1 bouyer * attached devices. 579 1.1 bouyer */ 580 1.1 bouyer switch (bootdev_class) { 581 1.1 bouyer case DV_DISK: 582 1.1 bouyer if (device_is_a(dev, "wd") && strcmp(name, bootdev) == 0) { 583 1.1 bouyer if (booted_device == NULL) 584 1.1 bouyer booted_device = dev; 585 1.1 bouyer } else { 586 1.1 bouyer /* XXX this really only works safely for usb0... */ 587 1.1 bouyer if ((device_is_a(dev, "sd") || 588 1.1 bouyer device_is_a(dev, "cd") == 0) && 589 1.1 bouyer strncmp(bootdev, "usb", 3) == 0 && 590 1.1 bouyer strcmp(name + 2, bootdev + 3) == 0) { 591 1.1 bouyer if (booted_device == NULL) 592 1.1 bouyer booted_device = dev; 593 1.1 bouyer } 594 1.1 bouyer } 595 1.1 bouyer break; 596 1.1 bouyer case DV_IFNET: 597 1.1 bouyer /* 598 1.1 bouyer * This relies on the onboard Ethernet interface being 599 1.1 bouyer * attached before any other (usb) interface. 600 1.1 bouyer */ 601 1.1 bouyer if (booted_device == NULL) 602 1.1 bouyer booted_device = dev; 603 1.1 bouyer break; 604 1.1 bouyer default: 605 1.1 bouyer break; 606 1.1 bouyer } 607 1.1 bouyer } 608