1 /* $OpenBSD: generic2e_machdep.c,v 1.10 2018/02/24 11:42:31 visa Exp $ */ 2 3 /* 4 * Copyright (c) 2010 Miodrag Vallat. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 /*- 19 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. 20 * All rights reserved. 21 * 22 * This code is derived from software contributed to The NetBSD Foundation 23 * by Jason R. Thorpe. 24 * 25 * Redistribution and use in source and binary forms, with or without 26 * modification, are permitted provided that the following conditions 27 * are met: 28 * 1. Redistributions of source code must retain the above copyright 29 * notice, this list of conditions and the following disclaimer. 30 * 2. Redistributions in binary form must reproduce the above copyright 31 * notice, this list of conditions and the following disclaimer in the 32 * documentation and/or other materials provided with the distribution. 33 * 34 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 35 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 37 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 43 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 44 * POSSIBILITY OF SUCH DAMAGE. 45 */ 46 47 /* 48 * Generic Loongson 2E code and configuration data. 49 */ 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/device.h> 54 55 #include <machine/autoconf.h> 56 #include <machine/cpu.h> 57 #include <mips64/mips_cpu.h> 58 #include <machine/pmon.h> 59 60 #include <dev/ic/i8259reg.h> 61 62 #include <dev/isa/isareg.h> 63 #include <dev/isa/isavar.h> 64 65 #include <dev/pci/pcireg.h> 66 #include <dev/pci/pcivar.h> 67 #include <dev/pci/pcidevs.h> 68 69 #include <loongson/dev/bonitoreg.h> 70 #include <loongson/dev/bonitovar.h> 71 #include <loongson/dev/bonito_irq.h> 72 73 #include "com.h" 74 75 #if NCOM > 0 76 #include <sys/termios.h> 77 #include <dev/ic/comvar.h> 78 extern struct mips_bus_space bonito_pci_io_space_tag; 79 #endif 80 81 void generic2e_device_register(struct device *, void *); 82 void generic2e_reset(void); 83 84 void generic2e_setup(void); 85 86 void generic2e_pci_attach_hook(pci_chipset_tag_t); 87 int generic2e_intr_map(int, int, int); 88 89 void generic2e_isa_attach_hook(struct device *, struct device *, 90 struct isabus_attach_args *); 91 void *generic2e_isa_intr_establish(void *, int, int, int, int (*)(void *), 92 void *, char *); 93 void generic2e_isa_intr_disestablish(void *, void *); 94 95 uint32_t generic2e_isa_intr(uint32_t, struct trapframe *); 96 97 void via686sb_setup(pci_chipset_tag_t, int); 98 99 /* PnP IRQ assignment for VIA686 SuperIO components */ 100 #define VIA686_IRQ_PCIA 9 101 #define VIA686_IRQ_PCIB 10 102 #define VIA686_IRQ_PCIC 11 103 #define VIA686_IRQ_PCID 13 104 105 static int generic2e_via686sb_dev = -1; 106 107 const struct bonito_config generic2e_bonito = { 108 .bc_adbase = 11, 109 110 .bc_gpioIE = 0xffffffff, 111 .bc_intEdge = BONITO_INTRMASK_SYSTEMERR | BONITO_INTRMASK_MASTERERR | 112 BONITO_INTRMASK_RETRYERR | BONITO_INTRMASK_MBOX, 113 .bc_intSteer = 0, 114 .bc_intPol = 0, 115 116 .bc_attach_hook = generic2e_pci_attach_hook, 117 .bc_intr_map = generic2e_intr_map 118 }; 119 120 const struct legacy_io_range generic2e_legacy_ranges[] = { 121 /* no isa space access restrictions */ 122 { 0, BONITO_PCIIO_LEGACY }, 123 124 { 0 } 125 }; 126 127 struct mips_isa_chipset generic2e_isa_chipset = { 128 .ic_v = NULL, 129 130 .ic_attach_hook = generic2e_isa_attach_hook, 131 .ic_intr_establish = generic2e_isa_intr_establish, 132 .ic_intr_disestablish = generic2e_isa_intr_disestablish 133 }; 134 135 const struct platform generic2e_platform = { 136 .system_type = LOONGSON_2E, 137 .vendor = "Generic", 138 .product = "Loongson2E", 139 140 .bonito_config = &generic2e_bonito, 141 .isa_chipset = &generic2e_isa_chipset, 142 .legacy_io_ranges = generic2e_legacy_ranges, 143 144 .setup = generic2e_setup, 145 .device_register = generic2e_device_register, 146 147 .powerdown = NULL, 148 .reset = generic2e_reset 149 }; 150 151 /* 152 * PCI model specific routines 153 */ 154 155 void 156 generic2e_pci_attach_hook(pci_chipset_tag_t pc) 157 { 158 pcireg_t id; 159 pcitag_t tag; 160 int dev; 161 162 /* 163 * Check for a VIA 686 southbridge; if one is found, remember 164 * its location, needed by generic2e_intr_map(). 165 */ 166 167 for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) { 168 tag = pci_make_tag(pc, 0, dev, 0); 169 id = pci_conf_read(pc, tag, PCI_ID_REG); 170 if (id == PCI_ID_CODE(PCI_VENDOR_VIATECH, 171 PCI_PRODUCT_VIATECH_VT82C686A_ISA)) { 172 generic2e_via686sb_dev = dev; 173 break; 174 } 175 } 176 177 if (generic2e_via686sb_dev != 0) 178 via686sb_setup(pc, generic2e_via686sb_dev); 179 } 180 181 int 182 generic2e_intr_map(int dev, int fn, int pin) 183 { 184 if (dev == generic2e_via686sb_dev) { 185 switch (fn) { 186 case 1: /* PCIIDE */ 187 /* will use compat interrupt */ 188 break; 189 case 2: /* USB */ 190 return BONITO_ISA_IRQ(VIA686_IRQ_PCIB); 191 case 3: /* USB */ 192 return BONITO_ISA_IRQ(VIA686_IRQ_PCIC); 193 case 4: /* power management, SMBus */ 194 break; 195 case 5: /* Audio */ 196 return BONITO_ISA_IRQ(VIA686_IRQ_PCIA); 197 case 6: /* Modem */ 198 break; 199 default: 200 break; 201 } 202 } else { 203 return BONITO_DIRECT_IRQ(BONITO_INTR_GPIN + 204 pin - PCI_INTERRUPT_PIN_A); 205 } 206 207 return -1; 208 } 209 210 /* 211 * ISA model specific routines 212 */ 213 214 void 215 generic2e_isa_attach_hook(struct device *parent, struct device *self, 216 struct isabus_attach_args *iba) 217 { 218 set_intr(INTPRI_ISA, CR_INT_3, generic2e_isa_intr); 219 loongson_generic_isa_attach_hook(parent, self, iba); 220 } 221 222 void * 223 generic2e_isa_intr_establish(void *v, int irq, int type, int level, 224 int (*handler)(void *), void *arg, char *name) 225 { 226 /* XXX check type, update elcr */ 227 return bonito_intr_establish(BONITO_ISA_IRQ(irq), type, level, 228 handler, arg, name); 229 } 230 231 void 232 generic2e_isa_intr_disestablish(void *v, void *ih) 233 { 234 /* XXX update elcr */ 235 bonito_intr_disestablish(ih); 236 } 237 238 uint32_t 239 generic2e_isa_intr(uint32_t hwpend, struct trapframe *frame) 240 { 241 struct intrhand *ih; 242 uint64_t isr, mask = 0; 243 int rc, irq, ret; 244 uint8_t ocw1, ocw2; 245 extern uint loongson_isaimr; 246 247 for (;;) { 248 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = 249 OCW3_SELECT | OCW3_POLL; 250 ocw1 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3); 251 if ((ocw1 & OCW3_POLL_PENDING) == 0) 252 break; 253 254 irq = OCW3_POLL_IRQ(ocw1); 255 256 if (irq == 2) /* cascade */ { 257 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = 258 OCW3_SELECT | OCW3_POLL; 259 ocw2 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3); 260 if (ocw2 & OCW3_POLL_PENDING) 261 irq = OCW3_POLL_IRQ(ocw2); 262 else 263 irq = 2; 264 } else 265 ocw2 = 0; 266 267 /* 268 * Mask the interrupt before servicing it. 269 */ 270 isr = 1UL << irq; 271 loongson_set_isa_imr(loongson_isaimr & ~isr); 272 273 /* 274 * If interrupt is spl-masked, wait for splx() 275 * to reenable it when necessary. 276 */ 277 if ((isr & BONITO_ISA_MASK(bonito_imask[frame->ipl])) != 0) 278 continue; 279 else 280 mask |= isr; 281 282 rc = 0; 283 for (ih = bonito_intrhand[BONITO_ISA_IRQ(irq)]; ih != NULL; 284 ih = ih->ih_next) { 285 splraise(ih->ih_level); 286 287 ret = (*ih->ih_fun)(ih->ih_arg); 288 if (ret) { 289 rc = 1; 290 ih->ih_count.ec_count++; 291 } 292 293 curcpu()->ci_ipl = frame->ipl; 294 295 if (ret == 1) 296 break; 297 } 298 299 /* Send a specific EOI to the 8259. */ 300 loongson_isa_specific_eoi(irq); 301 302 if (rc == 0) { 303 printf("spurious isa interrupt %d\n", irq); 304 #ifdef DEBUG 305 printf("ICU1 %02x ICU2 %02x ipl %d mask %08x" 306 " isaimr %08x\n", ocw1, ocw2, frame->ipl, 307 bonito_imask[frame->ipl], loongson_isaimr); 308 #ifdef DDB 309 db_enter(); 310 #endif 311 #endif 312 } 313 } 314 315 /* 316 * Reenable interrupts which have been serviced. 317 */ 318 if (mask != 0) 319 loongson_set_isa_imr(loongson_isaimr | mask); 320 321 return mask == 0 ? 0 : hwpend; 322 } 323 324 /* 325 * Other model specific routines 326 */ 327 328 void 329 generic2e_reset() 330 { 331 REGVAL(LOONGSON_GENCFG) &= ~BONITO_GENCFG_CPUSELFRESET; 332 REGVAL(LOONGSON_GENCFG) |= BONITO_GENCFG_CPUSELFRESET; 333 delay(1000000); 334 } 335 336 void 337 generic2e_setup(void) 338 { 339 #if NCOM > 0 340 const char *envvar; 341 int serial; 342 343 envvar = pmon_getenv("nokbd"); 344 serial = envvar != NULL; 345 envvar = pmon_getenv("novga"); 346 serial = serial && envvar != NULL; 347 348 if (serial) { 349 comconsiot = &bonito_pci_io_space_tag; 350 comconsaddr = 0x3f8; 351 comconsrate = 115200; /* default PMON console speed */ 352 } 353 #endif 354 355 bonito_early_setup(); 356 } 357 358 void 359 generic2e_device_register(struct device *dev, void *aux) 360 { 361 const char *drvrname = dev->dv_cfdata->cf_driver->cd_name; 362 const char *name = dev->dv_xname; 363 364 if (dev->dv_class != bootdev_class) 365 return; 366 367 /* 368 * The device numbering must match. There's no way 369 * pmon tells us more info. Depending on the usb slot 370 * and hubs used you may be lucky. Also, assume umass/sd for usb 371 * attached devices. 372 */ 373 switch (bootdev_class) { 374 case DV_DISK: 375 if (strcmp(drvrname, "wd") == 0 && strcmp(name, bootdev) == 0) 376 bootdv = dev; 377 else { 378 /* XXX this really only works safely for usb0... */ 379 if ((strcmp(drvrname, "sd") == 0 || 380 strcmp(drvrname, "cd") == 0) && 381 strncmp(bootdev, "usb", 3) == 0 && 382 strcmp(name + 2, bootdev + 3) == 0) 383 bootdv = dev; 384 } 385 break; 386 case DV_IFNET: 387 /* 388 * This relies on the onboard Ethernet interface being 389 * attached before any other (usb) interface. 390 */ 391 bootdv = dev; 392 break; 393 default: 394 break; 395 } 396 } 397 398 /* 399 * Initialize a VIA686 south bridge. 400 * 401 * PMON apparently does not perform enough initialization; one may argue this 402 * could be done with a specific pcib(4) driver, but then no other system 403 * will hopefully need this, so keep it local to the 2E setup code. 404 */ 405 406 #define VIA686_ISA_ROM_CONTROL 0x40 407 #define VIA686_ROM_WRITE_ENABLE 0x00000001 408 #define VIA686_NO_ROM_WAIT_STATE 0x00000002 409 #define VIA686_EXTEND_ALE 0x00000004 410 #define VIA686_IO_RECOVERY_TIME 0x00000008 411 #define VIA686_CHIPSET_EXTRA_WAIT_STATES 0x00000010 412 #define VIA686_ISA_EXTRA_WAIT_STATES 0x00000020 413 #define VIA686_ISA_EXTENDED_BUS_READY 0x00000040 414 #define VIA686_ISA_EXTRA_COMMAND_DELAY 0x00000080 415 #define VIA686_ISA_REFRESH 0x00000100 416 #define VIA686_DOUBLE_DMA_CLOCK 0x00000800 417 #define VIA686_PORT_92_FAST_RESET 0x00002000 418 #define VIA686_IO_MEDIUM_RECOVERY_TIME 0x00004000 419 #define VIA686_KBC_DMA_MISC12 0x44 420 #define VIA686_ISA_MASTER_TO_LINE_BUFFER 0x00008000 421 #define VIA686_POSTED_MEMORY_WRITE_ENABLE 0x00010000 422 #define VIA686_PCI_BURST_INTERRUPTABLE 0x00020000 423 #define VIA686_FLUSH_LINE_BUFFER_ON_INTR 0x00200000 424 #define VIA686_GATE_INTR 0x00400000 425 #define VIA686_PCI_MASTER_WRITE_WAIT_STATE 0x00800000 426 #define VIA686_PCI_RESET 0x01000000 427 #define VIA686_PCI_READ_DELAY_TRANSACTION_TMO 0x02000000 428 #define VIA686_PCI_WRITE_DELAY_TRANSACTION_TMO 0x04000000 429 #define VIA686_ICR_SHADOW_ENABLE 0x10000000 430 #define VIA686_EISA_PORT_4D0_4D1_ENABLE 0x20000000 431 #define VIA686_PCI_DELAY_TRANSACTION_ENABLE 0x40000000 432 #define VIA686_CPU_RESET_SOURCE_INIT 0x80000000 433 #define VIA686_MISC3_IDE_INTR 0x48 434 #define VIA686_IDE_PRIMARY_CHAN_MASK 0x00030000 435 #define VIA686_IDE_PRIMARY_CHAN_SHIFT 16 436 #define VIA686_IDE_SECONDARY_CHAN_MASK 0x000c0000 437 #define VIA686_IDE_SECONDARY_CHAN_SHIFT 18 438 #define VIA686_IDE_IRQ14 00 439 #define VIA686_IDE_IRQ15 01 440 #define VIA686_IDE_IRQ10 02 441 #define VIA686_IDE_IRQ11 03 442 #define VIA686_IDE_PGNT 0x00800000 443 #define VIA686_PNP_DMA_IRQ 0x50 444 #define VIA686_DMA_FDC_MASK 0x00000003 445 #define VIA686_DMA_FDC_SHIFT 0 446 #define VIA686_DMA_LPT_MASK 0x0000000c 447 #define VIA686_DMA_LPT_SHIFT 2 448 #define VIA686_IRQ_FDC_MASK 0x00000f00 449 #define VIA686_IRQ_FDC_SHIFT 8 450 #define VIA686_IRQ_LPT_MASK 0x0000f000 451 #define VIA686_IRQ_LPT_SHIFT 12 452 #define VIA686_IRQ_COM0_MASK 0x000f0000 453 #define VIA686_IRQ_COM0_SHIFT 16 454 #define VIA686_IRQ_COM1_MASK 0x00f00000 455 #define VIA686_IRQ_COM1_SHIFT 20 456 #define VIA686_PCI_LEVEL_PNP_IRQ2 0x54 457 #define VIA686_PCI_IRQD_EDGE 0x00000001 458 #define VIA686_PCI_IRQC_EDGE 0x00000002 459 #define VIA686_PCI_IRQB_EDGE 0x00000004 460 #define VIA686_PCI_IRQA_EDGE 0x00000008 461 #define VIA686_IRQ_PCIA_MASK 0x0000f000 462 #define VIA686_IRQ_PCIA_SHIFT 12 463 #define VIA686_IRQ_PCIB_MASK 0x000f0000 464 #define VIA686_IRQ_PCIB_SHIFT 16 465 #define VIA686_IRQ_PCIC_MASK 0x00f00000 466 #define VIA686_IRQ_PCIC_SHIFT 20 467 #define VIA686_IRQ_PCID_MASK 0xf0000000 468 #define VIA686_IRQ_PCID_SHIFT 28 469 470 void 471 via686sb_setup(pci_chipset_tag_t pc, int dev) 472 { 473 pcitag_t tag; 474 pcireg_t reg; 475 uint elcr; 476 477 tag = pci_make_tag(pc, 0, dev, 0); 478 479 /* 480 * Generic ISA bus initialization. 481 */ 482 483 reg = pci_conf_read(pc, tag, VIA686_ISA_ROM_CONTROL); 484 reg |= VIA686_IO_RECOVERY_TIME | VIA686_ISA_REFRESH; 485 pci_conf_write(pc, tag, VIA686_ISA_ROM_CONTROL, reg); 486 487 reg = pci_conf_read(pc, tag, VIA686_KBC_DMA_MISC12); 488 reg |= VIA686_CPU_RESET_SOURCE_INIT | 489 VIA686_PCI_DELAY_TRANSACTION_ENABLE | 490 VIA686_EISA_PORT_4D0_4D1_ENABLE | 491 VIA686_PCI_WRITE_DELAY_TRANSACTION_TMO | 492 VIA686_PCI_READ_DELAY_TRANSACTION_TMO | 493 VIA686_PCI_MASTER_WRITE_WAIT_STATE | VIA686_GATE_INTR | 494 VIA686_FLUSH_LINE_BUFFER_ON_INTR; 495 reg &= ~VIA686_ISA_MASTER_TO_LINE_BUFFER; 496 pci_conf_write(pc, tag, VIA686_KBC_DMA_MISC12, reg); 497 498 /* 499 * SuperIO devices interrupt and DMA setup. 500 */ 501 502 reg = pci_conf_read(pc, tag, VIA686_MISC3_IDE_INTR); 503 reg &= ~(VIA686_IDE_PRIMARY_CHAN_MASK | VIA686_IDE_SECONDARY_CHAN_MASK); 504 reg |= (VIA686_IDE_IRQ14 << VIA686_IDE_PRIMARY_CHAN_SHIFT); 505 reg |= (VIA686_IDE_IRQ15 << VIA686_IDE_SECONDARY_CHAN_SHIFT); 506 reg |= VIA686_IDE_PGNT; 507 pci_conf_write(pc, tag, VIA686_MISC3_IDE_INTR, reg); 508 509 reg = pci_conf_read(pc, tag, VIA686_PNP_DMA_IRQ); 510 reg &= ~(VIA686_DMA_FDC_MASK | VIA686_DMA_LPT_MASK); 511 reg |= (2 << VIA686_DMA_FDC_SHIFT) | (3 << VIA686_DMA_LPT_SHIFT); 512 reg &= ~(VIA686_IRQ_FDC_MASK | VIA686_IRQ_LPT_MASK); 513 reg |= (6 << VIA686_IRQ_FDC_SHIFT) | (7 << VIA686_IRQ_LPT_SHIFT); 514 reg &= ~(VIA686_IRQ_COM0_MASK | VIA686_IRQ_COM1_MASK); 515 reg |= (4 << VIA686_IRQ_COM0_SHIFT) | (3 << VIA686_IRQ_COM1_SHIFT); 516 517 reg = pci_conf_read(pc, tag, VIA686_PCI_LEVEL_PNP_IRQ2); 518 reg &= ~(VIA686_PCI_IRQA_EDGE | VIA686_PCI_IRQB_EDGE | 519 VIA686_PCI_IRQC_EDGE | VIA686_PCI_IRQD_EDGE); 520 reg &= ~(VIA686_IRQ_PCIA_MASK | VIA686_IRQ_PCIB_MASK | 521 VIA686_IRQ_PCIC_MASK | VIA686_IRQ_PCID_MASK); 522 reg |= (VIA686_IRQ_PCIA << VIA686_IRQ_PCIA_SHIFT) | 523 (VIA686_IRQ_PCIB << VIA686_IRQ_PCIB_SHIFT) | 524 (VIA686_IRQ_PCIC << VIA686_IRQ_PCIC_SHIFT) | 525 (VIA686_IRQ_PCID << VIA686_IRQ_PCID_SHIFT); 526 527 /* 528 * Interrupt controller setup. 529 */ 530 531 /* reset; program device, four bytes */ 532 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW1) = 533 ICW1_SELECT | ICW1_IC4; 534 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW2) = ICW2_VECTOR(0); 535 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW3) = ICW3_CASCADE(2); 536 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW4) = ICW4_8086; 537 /* leave interrupts masked */ 538 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1) = 0xff; 539 /* special mask mode (if available) */ 540 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = 541 OCW3_SELECT | OCW3_SSMM | OCW3_SMM; 542 /* read IRR by default. */ 543 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = OCW3_SELECT | OCW3_RR; 544 545 /* reset; program device, four bytes */ 546 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW1) = 547 ICW1_SELECT | ICW1_IC4; 548 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW2) = ICW2_VECTOR(8); 549 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW3) = ICW3_SIC(2); 550 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW4) = ICW4_8086; 551 /* leave interrupts masked */ 552 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1) = 0xff; 553 /* special mask mode (if available) */ 554 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = 555 OCW3_SELECT | OCW3_SSMM | OCW3_SMM; 556 /* read IRR by default. */ 557 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = OCW3_SELECT | OCW3_RR; 558 559 /* setup ELCR: PCI interrupts are level-triggered. */ 560 elcr = (1 << VIA686_IRQ_PCIA) | (1 << VIA686_IRQ_PCIB) | 561 (1 << VIA686_IRQ_PCIC) | (1 << VIA686_IRQ_PCID); 562 REGVAL8(BONITO_PCIIO_BASE + 0x4d0) = (elcr >> 0) & 0xff; 563 REGVAL8(BONITO_PCIIO_BASE + 0x4d1) = (elcr >> 8) & 0xff; 564 565 mips_sync(); 566 567 /* 568 * Update interrupt information for secondary functions. 569 * Although this information is not used by pci_intr_establish() 570 * because of generic2e_intr_map() behaviour, it seems to be 571 * required to complete proper interrupt routing. 572 */ 573 574 tag = pci_make_tag(pc, 0, dev, 2); 575 reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 576 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); 577 reg |= VIA686_IRQ_PCIB << PCI_INTERRUPT_LINE_SHIFT; 578 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg); 579 580 tag = pci_make_tag(pc, 0, dev, 3); 581 reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 582 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); 583 reg |= VIA686_IRQ_PCIC << PCI_INTERRUPT_LINE_SHIFT; 584 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg); 585 586 tag = pci_make_tag(pc, 0, dev, 5); 587 reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 588 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); 589 reg |= VIA686_IRQ_PCIA << PCI_INTERRUPT_LINE_SHIFT; 590 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg); 591 } 592