1 /* $OpenBSD: generic2e_machdep.c,v 1.2 2011/04/15 20:40:06 deraadt 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 #include <sys/cdefs.h> 51 __KERNEL_RCSID(0, "$NetBSD: generic2e_machdep.c,v 1.5 2015/06/09 16:10:48 macallan Exp $"); 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/device.h> 56 #include <sys/types.h> 57 58 59 #include <dev/ic/i8259reg.h> 60 61 #include <dev/isa/isareg.h> 62 #include <dev/isa/isavar.h> 63 64 #include <dev/pci/pcireg.h> 65 #include <dev/pci/pcivar.h> 66 #include <dev/pci/pcidevs.h> 67 68 #include <mips/cpuregs.h> 69 #include <mips/bonito/bonitoreg.h> 70 #include <mips/bonito/bonitovar.h> 71 72 #include <evbmips/loongson/autoconf.h> 73 #include <mips/pmon/pmon.h> 74 #include <evbmips/loongson/loongson_intr.h> 75 #include <evbmips/loongson/loongson_isa.h> 76 #include <evbmips/loongson/loongson_bus_defs.h> 77 78 #include "com.h" 79 #include "isa.h" 80 81 #if NCOM > 0 82 #include <sys/termios.h> 83 #include <dev/ic/comvar.h> 84 #endif 85 86 void generic2e_device_register(device_t, void *); 87 void generic2e_reset(void); 88 89 void generic2e_setup(void); 90 91 void generic2e_pci_attach_hook(device_t, device_t, 92 struct pcibus_attach_args *); 93 int generic2e_intr_map(int, int, int, pci_intr_handle_t *); 94 95 void generic2e_isa_attach_hook(device_t, device_t, 96 struct isabus_attach_args *); 97 void *generic2e_isa_intr_establish(void *, int, int, int, 98 int (*)(void *), void *); 99 void generic2e_isa_intr_disestablish(void *, void *); 100 const struct evcnt * generic2e_isa_intr_evcnt(void *, int); 101 const char * generic2e_isa_intr_string(void *, int, char *, size_t); 102 103 void generic2e_isa_intr(int, vaddr_t, uint32_t); 104 105 void via686sb_setup(pci_chipset_tag_t, int); 106 107 /* PnP IRQ assignment for VIA686 SuperIO components */ 108 #define VIA686_IRQ_PCIA 9 109 #define VIA686_IRQ_PCIB 10 110 #define VIA686_IRQ_PCIC 11 111 #define VIA686_IRQ_PCID 13 112 113 static int generic2e_via686sb_dev = -1; 114 115 const struct bonito_config generic2e_bonito = { 116 .bc_adbase = 11, 117 118 .bc_gpioIE = 0xffffffff, 119 .bc_intEdge = BONITO_INTRMASK_SYSTEMERR | BONITO_INTRMASK_MASTERERR | 120 BONITO_INTRMASK_RETRYERR | BONITO_INTRMASK_MBOX, 121 .bc_intSteer = 0, 122 .bc_intPol = 0, 123 124 .bc_attach_hook = generic2e_pci_attach_hook, 125 }; 126 127 const struct legacy_io_range generic2e_legacy_ranges[] = { 128 /* no isa space access restrictions */ 129 { 0, BONITO_PCIIO_LEGACY }, 130 131 { 0 } 132 }; 133 134 struct mips_isa_chipset generic2e_isa_chipset = { 135 .ic_v = NULL, 136 137 .ic_attach_hook = generic2e_isa_attach_hook, 138 .ic_intr_establish = generic2e_isa_intr_establish, 139 .ic_intr_disestablish = generic2e_isa_intr_disestablish, 140 .ic_intr_evcnt = generic2e_isa_intr_evcnt, 141 .ic_intr_string = generic2e_isa_intr_string, 142 }; 143 144 const struct platform generic2e_platform = { 145 .system_type = LOONGSON_2E, 146 .vendor = "Generic", 147 .product = "Loongson2E", 148 149 .bonito_config = &generic2e_bonito, 150 .isa_chipset = &generic2e_isa_chipset, 151 .legacy_io_ranges = generic2e_legacy_ranges, 152 .bonito_mips_intr = MIPS_INT_MASK_0, 153 .isa_mips_intr = MIPS_INT_MASK_3, 154 .isa_intr = generic2e_isa_intr, 155 .p_pci_intr_map = generic2e_intr_map, 156 .irq_map = loongson2e_irqmap, 157 158 .setup = generic2e_setup, 159 .device_register = generic2e_device_register, 160 161 .powerdown = NULL, 162 .reset = generic2e_reset 163 }; 164 165 /* 166 * PCI model specific routines 167 */ 168 169 void 170 generic2e_pci_attach_hook(device_t parent, device_t self, 171 struct pcibus_attach_args *pba) 172 { 173 pci_chipset_tag_t pc = pba->pba_pc; 174 pcireg_t id; 175 pcitag_t tag; 176 int dev; 177 178 if (pba->pba_bus != 0) 179 return; 180 181 /* 182 * Check for a VIA 686 southbridge; if one is found, remember 183 * its location, needed by generic2e_intr_map(). 184 */ 185 186 for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) { 187 tag = pci_make_tag(pc, 0, dev, 0); 188 id = pci_conf_read(pc, tag, PCI_ID_REG); 189 if (id == PCI_ID_CODE(PCI_VENDOR_VIATECH, 190 PCI_PRODUCT_VIATECH_VT82C686A_ISA)) { 191 generic2e_via686sb_dev = dev; 192 break; 193 } 194 } 195 196 if (generic2e_via686sb_dev != 0) 197 via686sb_setup(pc, generic2e_via686sb_dev); 198 } 199 200 int 201 generic2e_intr_map(int dev, int fn, int pin, pci_intr_handle_t *ihp) 202 { 203 if (dev == generic2e_via686sb_dev) { 204 switch (fn) { 205 case 1: /* PCIIDE */ 206 /* will use compat interrupt */ 207 break; 208 case 2: /* USB */ 209 *ihp = BONITO_ISA_IRQ(VIA686_IRQ_PCIB); 210 return 0; 211 case 3: /* USB */ 212 *ihp = BONITO_ISA_IRQ(VIA686_IRQ_PCIC); 213 return 0; 214 case 4: /* power management, SMBus */ 215 break; 216 case 5: /* Audio */ 217 *ihp = BONITO_ISA_IRQ(VIA686_IRQ_PCIA); 218 return 0; 219 case 6: /* Modem */ 220 break; 221 default: 222 break; 223 } 224 } else { 225 *ihp = BONITO_DIRECT_IRQ(BONITO_INTR_GPIN + 226 pin - PCI_INTERRUPT_PIN_A); 227 return 0; 228 } 229 230 return 1; 231 } 232 233 /* 234 * ISA model specific routines 235 */ 236 237 void 238 generic2e_isa_attach_hook(device_t parent, device_t self, 239 struct isabus_attach_args *iba) 240 { 241 loongson_set_isa_imr(loongson_isaimr); 242 } 243 244 void * 245 generic2e_isa_intr_establish(void *v, int irq, int type, int level, 246 int (*handler)(void *), void *arg) 247 { 248 void *ih; 249 uint imr; 250 251 ih = evbmips_intr_establish(BONITO_ISA_IRQ(irq), handler, arg); 252 if (ih == NULL) 253 return NULL; 254 /* enable interrupt */ 255 imr = loongson_isaimr; 256 imr |= (1 << irq); 257 loongson_set_isa_imr(imr); 258 return ih; 259 } 260 261 void 262 generic2e_isa_intr_disestablish(void *v, void *ih) 263 { 264 evbmips_intr_disestablish(ih); 265 } 266 267 const struct evcnt * 268 generic2e_isa_intr_evcnt(void *v, int irq) 269 { 270 271 if (irq == 0 || irq >= BONITO_NISA || irq == 2) 272 panic("generic2e_isa_intr_evcnt: bogus isa irq 0x%x", irq); 273 274 return (&bonito_intrhead[BONITO_ISA_IRQ(irq)].intr_count); 275 } 276 277 const char * 278 generic2e_isa_intr_string(void *v, int irq, char *buf, size_t len) 279 { 280 if (irq == 0 || irq >= BONITO_NISA || irq == 2) 281 panic("generic2e_isa_intr_string: bogus isa irq 0x%x", irq); 282 283 return loongson_intr_string(&generic2e_bonito, irq, buf, len); 284 } 285 286 void 287 generic2e_isa_intr(int ipl, vaddr_t pc, uint32_t ipending) 288 { 289 #if NISA > 0 290 struct evbmips_intrhand *ih; 291 uint64_t isr, mask = 0; 292 int rc, irq, ret; 293 uint8_t ocw1, ocw2; 294 295 for (;;) { 296 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = 297 OCW3_SELECT | OCW3_POLL; 298 ocw1 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3); 299 if ((ocw1 & OCW3_POLL_PENDING) == 0) 300 break; 301 302 irq = OCW3_POLL_IRQ(ocw1); 303 304 if (irq == 2) /* cascade */ { 305 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = 306 OCW3_SELECT | OCW3_POLL; 307 ocw2 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3); 308 if (ocw2 & OCW3_POLL_PENDING) 309 irq = OCW3_POLL_IRQ(ocw2); 310 else 311 irq = 2; 312 } else 313 ocw2 = 0; 314 315 /* 316 * Mask the interrupt before servicing it. 317 */ 318 isr = 1UL << irq; 319 loongson_set_isa_imr(loongson_isaimr & ~isr); 320 321 mask |= isr; 322 323 rc = 0; 324 LIST_FOREACH(ih, 325 &bonito_intrhead[BONITO_ISA_IRQ(irq)].intrhand_head, 326 ih_q) { 327 ret = (*ih->ih_func)(ih->ih_arg); 328 if (ret) { 329 rc = 1; 330 bonito_intrhead[BONITO_ISA_IRQ(irq)].intr_count.ev_count++; 331 } 332 333 if (ret == 1) 334 break; 335 } 336 337 /* Send a specific EOI to the 8259. */ 338 loongson_isa_specific_eoi(irq); 339 340 if (rc == 0) { 341 printf("spurious isa interrupt %d\n", irq); 342 } 343 } 344 345 /* 346 * Reenable interrupts which have been serviced. 347 */ 348 if (mask != 0) 349 loongson_set_isa_imr(loongson_isaimr | mask); 350 351 #endif 352 } 353 354 /* 355 * Other model specific routines 356 */ 357 358 void 359 generic2e_reset(void) 360 { 361 REGVAL(BONITO_BONGENCFG) &= ~BONITO_BONGENCFG_CPUSELFRESET; 362 REGVAL(BONITO_BONGENCFG) |= BONITO_BONGENCFG_CPUSELFRESET; 363 delay(1000000); 364 } 365 366 void 367 generic2e_setup(void) 368 { 369 #if NCOM > 0 370 const char *envvar; 371 int serial; 372 373 envvar = pmon_getenv("nokbd"); 374 serial = envvar != NULL; 375 envvar = pmon_getenv("novga"); 376 serial = serial && envvar != NULL; 377 378 if (serial) { 379 comconsiot = &bonito_iot; 380 comconsaddr = 0x3f8; 381 comconsrate = 115200; /* default PMON console speed */ 382 } 383 #endif 384 } 385 386 void 387 generic2e_device_register(device_t dev, void *aux) 388 { 389 const char *name = device_xname(dev); 390 391 if (device_class(dev) != bootdev_class) 392 return; 393 394 /* 395 * The device numbering must match. There's no way 396 * pmon tells us more info. Depending on the usb slot 397 * and hubs used you may be lucky. Also, assume umass/sd for usb 398 * attached devices. 399 */ 400 switch (bootdev_class) { 401 case DV_DISK: 402 if (device_is_a(dev, "wd") && strcmp(name, bootdev) == 0) { 403 if (booted_device == NULL) 404 booted_device = dev; 405 } else { 406 /* XXX this really only works safely for usb0... */ 407 if ((device_is_a(dev, "sd") || 408 device_is_a(dev, "cd")) && 409 strncmp(bootdev, "usb", 3) == 0 && 410 strcmp(name + 2, bootdev + 3) == 0) { 411 if (booted_device == NULL) 412 booted_device = dev; 413 } 414 } 415 break; 416 case DV_IFNET: 417 /* 418 * This relies on the onboard Ethernet interface being 419 * attached before any other (usb) interface. 420 */ 421 if (booted_device == NULL) 422 booted_device = dev; 423 break; 424 default: 425 break; 426 } 427 } 428 429 /* 430 * Initialize a VIA686 south bridge. 431 * 432 * PMON apparently does not perform enough initialization; one may argue this 433 * could be done with a specific pcib(4) driver, but then no other system 434 * will hopefully need this, so keep it local to the 2E setup code. 435 */ 436 437 #define VIA686_ISA_ROM_CONTROL 0x40 438 #define VIA686_ROM_WRITE_ENABLE 0x00000001 439 #define VIA686_NO_ROM_WAIT_STATE 0x00000002 440 #define VIA686_EXTEND_ALE 0x00000004 441 #define VIA686_IO_RECOVERY_TIME 0x00000008 442 #define VIA686_CHIPSET_EXTRA_WAIT_STATES 0x00000010 443 #define VIA686_ISA_EXTRA_WAIT_STATES 0x00000020 444 #define VIA686_ISA_EXTENDED_BUS_READY 0x00000040 445 #define VIA686_ISA_EXTRA_COMMAND_DELAY 0x00000080 446 #define VIA686_ISA_REFRESH 0x00000100 447 #define VIA686_DOUBLE_DMA_CLOCK 0x00000800 448 #define VIA686_PORT_92_FAST_RESET 0x00002000 449 #define VIA686_IO_MEDIUM_RECOVERY_TIME 0x00004000 450 #define VIA686_KBC_DMA_MISC12 0x44 451 #define VIA686_ISA_MASTER_TO_LINE_BUFFER 0x00008000 452 #define VIA686_POSTED_MEMORY_WRITE_ENABLE 0x00010000 453 #define VIA686_PCI_BURST_INTERRUPTABLE 0x00020000 454 #define VIA686_FLUSH_LINE_BUFFER_ON_INTR 0x00200000 455 #define VIA686_GATE_INTR 0x00400000 456 #define VIA686_PCI_MASTER_WRITE_WAIT_STATE 0x00800000 457 #define VIA686_PCI_RESET 0x01000000 458 #define VIA686_PCI_READ_DELAY_TRANSACTION_TMO 0x02000000 459 #define VIA686_PCI_WRITE_DELAY_TRANSACTION_TMO 0x04000000 460 #define VIA686_ICR_SHADOW_ENABLE 0x10000000 461 #define VIA686_EISA_PORT_4D0_4D1_ENABLE 0x20000000 462 #define VIA686_PCI_DELAY_TRANSACTION_ENABLE 0x40000000 463 #define VIA686_CPU_RESET_SOURCE_INIT 0x80000000 464 #define VIA686_MISC3_IDE_INTR 0x48 465 #define VIA686_IDE_PRIMARY_CHAN_MASK 0x00030000 466 #define VIA686_IDE_PRIMARY_CHAN_SHIFT 16 467 #define VIA686_IDE_SECONDARY_CHAN_MASK 0x000c0000 468 #define VIA686_IDE_SECONDARY_CHAN_SHIFT 18 469 #define VIA686_IDE_IRQ14 00 470 #define VIA686_IDE_IRQ15 01 471 #define VIA686_IDE_IRQ10 02 472 #define VIA686_IDE_IRQ11 03 473 #define VIA686_IDE_PGNT 0x00800000 474 #define VIA686_PNP_DMA_IRQ 0x50 475 #define VIA686_DMA_FDC_MASK 0x00000003 476 #define VIA686_DMA_FDC_SHIFT 0 477 #define VIA686_DMA_LPT_MASK 0x0000000c 478 #define VIA686_DMA_LPT_SHIFT 2 479 #define VIA686_IRQ_FDC_MASK 0x00000f00 480 #define VIA686_IRQ_FDC_SHIFT 8 481 #define VIA686_IRQ_LPT_MASK 0x0000f000 482 #define VIA686_IRQ_LPT_SHIFT 12 483 #define VIA686_IRQ_COM0_MASK 0x000f0000 484 #define VIA686_IRQ_COM0_SHIFT 16 485 #define VIA686_IRQ_COM1_MASK 0x00f00000 486 #define VIA686_IRQ_COM1_SHIFT 20 487 #define VIA686_PCI_LEVEL_PNP_IRQ2 0x54 488 #define VIA686_PCI_IRQD_EDGE 0x00000001 489 #define VIA686_PCI_IRQC_EDGE 0x00000002 490 #define VIA686_PCI_IRQB_EDGE 0x00000004 491 #define VIA686_PCI_IRQA_EDGE 0x00000008 492 #define VIA686_IRQ_PCIA_MASK 0x0000f000 493 #define VIA686_IRQ_PCIA_SHIFT 12 494 #define VIA686_IRQ_PCIB_MASK 0x000f0000 495 #define VIA686_IRQ_PCIB_SHIFT 16 496 #define VIA686_IRQ_PCIC_MASK 0x00f00000 497 #define VIA686_IRQ_PCIC_SHIFT 20 498 #define VIA686_IRQ_PCID_MASK 0xf0000000 499 #define VIA686_IRQ_PCID_SHIFT 28 500 501 void 502 via686sb_setup(pci_chipset_tag_t pc, int dev) 503 { 504 pcitag_t tag; 505 pcireg_t reg; 506 uint elcr; 507 508 tag = pci_make_tag(pc, 0, dev, 0); 509 510 /* 511 * Generic ISA bus initialization. 512 */ 513 514 reg = pci_conf_read(pc, tag, VIA686_ISA_ROM_CONTROL); 515 reg |= VIA686_IO_RECOVERY_TIME | VIA686_ISA_REFRESH; 516 pci_conf_write(pc, tag, VIA686_ISA_ROM_CONTROL, reg); 517 518 reg = pci_conf_read(pc, tag, VIA686_KBC_DMA_MISC12); 519 reg |= VIA686_CPU_RESET_SOURCE_INIT | 520 VIA686_PCI_DELAY_TRANSACTION_ENABLE | 521 VIA686_EISA_PORT_4D0_4D1_ENABLE | 522 VIA686_PCI_WRITE_DELAY_TRANSACTION_TMO | 523 VIA686_PCI_READ_DELAY_TRANSACTION_TMO | 524 VIA686_PCI_MASTER_WRITE_WAIT_STATE | VIA686_GATE_INTR | 525 VIA686_FLUSH_LINE_BUFFER_ON_INTR; 526 reg &= ~VIA686_ISA_MASTER_TO_LINE_BUFFER; 527 pci_conf_write(pc, tag, VIA686_KBC_DMA_MISC12, reg); 528 529 /* 530 * SuperIO devices interrupt and DMA setup. 531 */ 532 533 reg = pci_conf_read(pc, tag, VIA686_MISC3_IDE_INTR); 534 reg &= ~(VIA686_IDE_PRIMARY_CHAN_MASK | VIA686_IDE_SECONDARY_CHAN_MASK); 535 reg |= (VIA686_IDE_IRQ14 << VIA686_IDE_PRIMARY_CHAN_SHIFT); 536 reg |= (VIA686_IDE_IRQ15 << VIA686_IDE_SECONDARY_CHAN_SHIFT); 537 reg |= VIA686_IDE_PGNT; 538 pci_conf_write(pc, tag, VIA686_MISC3_IDE_INTR, reg); 539 540 reg = pci_conf_read(pc, tag, VIA686_PNP_DMA_IRQ); 541 reg &= ~(VIA686_DMA_FDC_MASK | VIA686_DMA_LPT_MASK); 542 reg |= (2 << VIA686_DMA_FDC_SHIFT) | (3 << VIA686_DMA_LPT_SHIFT); 543 reg &= ~(VIA686_IRQ_FDC_MASK | VIA686_IRQ_LPT_MASK); 544 reg |= (6 << VIA686_IRQ_FDC_SHIFT) | (7 << VIA686_IRQ_LPT_SHIFT); 545 reg &= ~(VIA686_IRQ_COM0_MASK | VIA686_IRQ_COM1_MASK); 546 reg |= (4 << VIA686_IRQ_COM0_SHIFT) | (3 << VIA686_IRQ_COM1_SHIFT); 547 548 reg = pci_conf_read(pc, tag, VIA686_PCI_LEVEL_PNP_IRQ2); 549 reg &= ~(VIA686_PCI_IRQA_EDGE | VIA686_PCI_IRQB_EDGE | 550 VIA686_PCI_IRQB_EDGE | VIA686_PCI_IRQD_EDGE); 551 reg &= ~(VIA686_IRQ_PCIA_MASK | VIA686_IRQ_PCIB_MASK | 552 VIA686_IRQ_PCIC_MASK | VIA686_IRQ_PCID_MASK); 553 reg |= (VIA686_IRQ_PCIA << VIA686_IRQ_PCIA_SHIFT) | 554 (VIA686_IRQ_PCIB << VIA686_IRQ_PCIB_SHIFT) | 555 (VIA686_IRQ_PCIC << VIA686_IRQ_PCIC_SHIFT) | 556 (VIA686_IRQ_PCID << VIA686_IRQ_PCID_SHIFT); 557 558 /* 559 * Interrupt controller setup. 560 */ 561 562 /* reset; program device, four bytes */ 563 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW1) = 564 ICW1_SELECT | ICW1_IC4; 565 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW2) = ICW2_VECTOR(0); 566 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW3) = ICW3_CASCADE(2); 567 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW4) = ICW4_8086; 568 /* leave interrupts masked */ 569 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1) = 0xff; 570 /* special mask mode (if available) */ 571 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = 572 OCW3_SELECT | OCW3_SSMM | OCW3_SMM; 573 /* read IRR by default. */ 574 REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = OCW3_SELECT | OCW3_RR; 575 576 /* reset; program device, four bytes */ 577 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW1) = 578 ICW1_SELECT | ICW1_IC4; 579 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW2) = ICW2_VECTOR(8); 580 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW3) = ICW3_SIC(2); 581 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW4) = ICW4_8086; 582 /* leave interrupts masked */ 583 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1) = 0xff; 584 /* special mask mode (if available) */ 585 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = 586 OCW3_SELECT | OCW3_SSMM | OCW3_SMM; 587 /* read IRR by default. */ 588 REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = OCW3_SELECT | OCW3_RR; 589 590 /* setup ELCR: PCI interrupts are level-triggered. */ 591 elcr = (1 << VIA686_IRQ_PCIA) | (1 << VIA686_IRQ_PCIB) | 592 (1 << VIA686_IRQ_PCIC) | (1 << VIA686_IRQ_PCID); 593 REGVAL8(BONITO_PCIIO_BASE + 0x4d0) = (elcr >> 0) & 0xff; 594 REGVAL8(BONITO_PCIIO_BASE + 0x4d1) = (elcr >> 8) & 0xff; 595 596 __asm__ __volatile__ ("sync" ::: "memory"); 597 598 /* 599 * Update interrupt information for secondary functions. 600 * Although this information is not used by pci_intr_establish() 601 * because of generic2e_intr_map() behaviour, it seems to be 602 * required to complete proper interrupt routing. 603 */ 604 605 tag = pci_make_tag(pc, 0, dev, 2); 606 reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 607 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); 608 reg |= VIA686_IRQ_PCIB << PCI_INTERRUPT_LINE_SHIFT; 609 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg); 610 611 tag = pci_make_tag(pc, 0, dev, 3); 612 reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 613 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); 614 reg |= VIA686_IRQ_PCIC << PCI_INTERRUPT_LINE_SHIFT; 615 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg); 616 617 tag = pci_make_tag(pc, 0, dev, 5); 618 reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 619 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); 620 reg |= VIA686_IRQ_PCIA << PCI_INTERRUPT_LINE_SHIFT; 621 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg); 622 } 623