idtpci.c revision 182901
1/* $NetBSD: idtpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */ 2 3/*- 4 * Copyright (c) 2007 David Young. 5 * Copyright (c) 2007 Oleskandr Tymoshenko. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or 8 * without modification, are permitted provided that the following 9 * conditions are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 3. The name of the author may not be used to endorse or promote 17 * products derived from this software without specific prior 18 * written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 27 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 */ 33/*- 34 * Copyright (c) 2006 Itronix Inc. 35 * All rights reserved. 36 * 37 * Written by Garrett D'Amore for Itronix Inc. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. The name of Itronix Inc. may not be used to endorse 48 * or promote products derived from this software without specific 49 * prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 55 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 56 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 58 * ON ANY THEORY OF LIABILITY, WHETHER IN 59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 61 * POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64#include <sys/cdefs.h> 65__FBSDID("$FreeBSD: head/sys/mips/idt/idtpci.c 182901 2008-09-10 03:49:08Z gonzo $"); 66 67#include <sys/param.h> 68#include <sys/systm.h> 69 70#include <sys/bus.h> 71#include <sys/interrupt.h> 72#include <sys/malloc.h> 73#include <sys/kernel.h> 74#include <sys/module.h> 75#include <sys/rman.h> 76 77#include <vm/vm.h> 78#include <vm/pmap.h> 79#include <vm/vm_extern.h> 80 81#include <machine/bus.h> 82#include <machine/cpu.h> 83#include <machine/pmap.h> 84 85#include <dev/pci/pcivar.h> 86#include <dev/pci/pcireg.h> 87 88#include <dev/pci/pcib_private.h> 89#include "pcib_if.h" 90 91#include <mips/idt/idtreg.h> 92 93#ifdef IDTPCI_DEBUG 94int idtpci_debug = 1; 95#define IDTPCI_DPRINTF(__fmt, ...) \ 96do { \ 97 if (idtpci_debug) \ 98 printf((__fmt), __VA_ARGS__); \ 99} while (/*CONSTCOND*/0) 100#else /* !IDTPCI_DEBUG */ 101#define IDTPCI_DPRINTF(__fmt, ...) do { } while (/*CONSTCOND*/0) 102#endif /* IDTPCI_DEBUG */ 103 104#define IDTPCI_TAG_BUS_MASK 0x007f0000 105#define IDTPCI_TAG_DEVICE_MASK 0x00007800 106#define IDTPCI_TAG_FUNCTION_MASK 0x00000300 107#define IDTPCI_TAG_REGISTER_MASK 0x0000007c 108 109#define IDTPCI_MAX_DEVICE 110 111#define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(IDT_BASE_PCI + (o))) 112#define REG_WRITE(o,v) (REG_READ(o)) = (v) 113 114unsigned int korina_fixup[24] = { 115 0x00000157, 0x00000000, 0x00003c04, 0x00000008, 0x18800001, 0x18000001, 116 0x48000008, 0x00000000, 0x00000000, 0x00000000, 0x011d0214, 0x00000000, 117 0x00000000, 0x00000000, 0x38080101, 0x00008080, 0x00000d6e, 0x00000000, 118 0x00000051, 0x00000000, 0x00000055, 0x18000000, 0x00000000, 0x00000000 119}; 120 121struct idtpci_softc { 122 device_t sc_dev; 123 124 int sc_busno; 125 struct rman sc_mem_rman[2]; 126 struct rman sc_io_rman[2]; 127 struct rman sc_irq_rman; 128 uint32_t sc_mem; 129 uint32_t sc_io; 130}; 131 132static uint32_t 133idtpci_make_addr(int bus, int slot, int func, int reg) 134{ 135 136 return 0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | reg; 137} 138 139static int 140idtpci_probe(device_t dev) 141{ 142 143 return (0); 144} 145 146static int 147idtpci_attach(device_t dev) 148{ 149 int busno = 0; 150 struct idtpci_softc *sc = device_get_softc(dev); 151 unsigned int pci_data, force_endianess = 0; 152 int i; 153 bus_addr_t addr; 154 155 sc->sc_dev = dev; 156 sc->sc_busno = busno; 157 158 sc->sc_io = 0; 159 sc->sc_mem = 0; 160 161 /* TODO: Check for host mode */ 162 163 /* Enabled PCI, IG mode, EAP mode */ 164 REG_WRITE(IDT_PCI_CNTL, IDT_PCI_CNTL_IGM | IDT_PCI_CNTL_EAP | 165 IDT_PCI_CNTL_EN); 166 /* Wait while "Reset in progress bit" set */ 167 while(1) { 168 pci_data = REG_READ(IDT_PCI_STATUS); 169 if((pci_data & IDT_PCI_STATUS_RIP) == 0) 170 break; 171 } 172 173 /* Reset status register */ 174 REG_WRITE(IDT_PCI_STATUS, 0); 175 /* Mask interrupts related to status register */ 176 REG_WRITE(IDT_PCI_STATUS_MASK, 0xffffffff); 177 178 /* Disable PCI decoupled access */ 179 REG_WRITE(IDT_PCI_DAC, 0); 180 /* Zero status and mask DA interrupts */ 181 REG_WRITE(IDT_PCI_DAS, 0); 182 REG_WRITE(IDT_PCI_DASM, 0x7f); 183 184 /* Init PCI messaging unit */ 185 /* Disable messaging interrupts */ 186 REG_WRITE(IDT_PCI_IIC, 0); 187 REG_WRITE(IDT_PCI_IIM, 0xffffffff); 188 REG_WRITE(IDT_PCI_OIC, 0); 189 REG_WRITE(IDT_PCI_OIM, 0); 190 191#ifdef __MIPSEB__ 192 force_endianess = IDT_PCI_LBA_FE; 193#endif 194 195 /* LBA0 -- memory window */ 196 REG_WRITE(IDT_PCI_LBA0, IDT_PCIMEM0_BASE); 197 REG_WRITE(IDT_PCI_LBA0_MAP, IDT_PCIMEM0_BASE); 198 REG_WRITE(IDT_PCI_LBA0_CNTL, IDT_PCI_LBA_SIZE_16MB | force_endianess); 199 pci_data = REG_READ(IDT_PCI_LBA0_CNTL); 200 201 /* LBA1 -- memory window */ 202 REG_WRITE(IDT_PCI_LBA1, IDT_PCIMEM1_BASE); 203 REG_WRITE(IDT_PCI_LBA1_MAP, IDT_PCIMEM1_BASE); 204 REG_WRITE(IDT_PCI_LBA1_CNTL, IDT_PCI_LBA_SIZE_256MB | force_endianess); 205 pci_data = REG_READ(IDT_PCI_LBA1_CNTL); 206 207 /* LBA2 -- IO window */ 208 REG_WRITE(IDT_PCI_LBA2, IDT_PCIMEM2_BASE); 209 REG_WRITE(IDT_PCI_LBA2_MAP, IDT_PCIMEM2_BASE); 210 REG_WRITE(IDT_PCI_LBA2_CNTL, IDT_PCI_LBA_SIZE_4MB | IDT_PCI_LBA_MSI | 211 force_endianess); 212 pci_data = REG_READ(IDT_PCI_LBA2_CNTL); 213 214 /* LBA3 -- IO window */ 215 REG_WRITE(IDT_PCI_LBA3, IDT_PCIMEM3_BASE); 216 REG_WRITE(IDT_PCI_LBA3_MAP, IDT_PCIMEM3_BASE); 217 REG_WRITE(IDT_PCI_LBA3_CNTL, IDT_PCI_LBA_SIZE_1MB | IDT_PCI_LBA_MSI | 218 force_endianess); 219 pci_data = REG_READ(IDT_PCI_LBA3_CNTL); 220 221 222 pci_data = REG_READ(IDT_PCI_CNTL) & ~IDT_PCI_CNTL_TNR; 223 REG_WRITE(IDT_PCI_CNTL, pci_data); 224 pci_data = REG_READ(IDT_PCI_CNTL); 225 226 /* Rewrite Target Control register with default values */ 227 REG_WRITE(IDT_PCI_TC, (IDT_PCI_TC_DTIMER << 8) | IDT_PCI_TC_RTIMER); 228 229 /* Perform Korina fixup */ 230 addr = idtpci_make_addr(0, 0, 0, 4); 231 for (i = 0; i < 24; i++) { 232 233 REG_WRITE(IDT_PCI_CFG_ADDR, addr); 234 REG_WRITE(IDT_PCI_CFG_DATA, korina_fixup[i]); 235 __asm__ volatile ("sync"); 236 237 REG_WRITE(IDT_PCI_CFG_ADDR, 0); 238 REG_WRITE(IDT_PCI_CFG_DATA, 0); 239 addr += 4; 240 } 241 242 /* Use KSEG1 to access IO ports for it is uncached */ 243 sc->sc_io = 0; 244 sc->sc_io_rman[0].rm_type = RMAN_ARRAY; 245 sc->sc_io_rman[0].rm_descr = "IDTPCI I/O Ports window 1"; 246 if (rman_init(&sc->sc_io_rman[0]) != 0 || 247 rman_manage_region(&sc->sc_io_rman[0], 248 IDT_PCIMEM2_BASE, IDT_PCIMEM2_BASE + IDT_PCIMEM2_SIZE - 1) != 0) { 249 panic("idtpci_attach: failed to set up I/O rman"); 250 } 251 252 sc->sc_io_rman[1].rm_type = RMAN_ARRAY; 253 sc->sc_io_rman[1].rm_descr = "IDTPCI I/O Ports window 2"; 254 if (rman_init(&sc->sc_io_rman[1]) != 0 || 255 rman_manage_region(&sc->sc_io_rman[1], 256 IDT_PCIMEM3_BASE, IDT_PCIMEM3_BASE + IDT_PCIMEM3_SIZE - 1) != 0) { 257 panic("idtpci_attach: failed to set up I/O rman"); 258 } 259 260 /* Use KSEG1 to access PCI memory for it is uncached */ 261 sc->sc_mem = 0; 262 sc->sc_mem_rman[0].rm_type = RMAN_ARRAY; 263 sc->sc_mem_rman[0].rm_descr = "IDTPCI PCI Memory window 1"; 264 if (rman_init(&sc->sc_mem_rman[0]) != 0 || 265 rman_manage_region(&sc->sc_mem_rman[0], 266 IDT_PCIMEM0_BASE, IDT_PCIMEM0_BASE + IDT_PCIMEM0_SIZE) != 0) { 267 panic("idtpci_attach: failed to set up memory rman"); 268 } 269 270 sc->sc_mem_rman[1].rm_type = RMAN_ARRAY; 271 sc->sc_mem_rman[1].rm_descr = "IDTPCI PCI Memory window 2"; 272 if (rman_init(&sc->sc_mem_rman[1]) != 0 || 273 rman_manage_region(&sc->sc_mem_rman[1], 274 IDT_PCIMEM1_BASE, IDT_PCIMEM1_BASE + IDT_PCIMEM1_SIZE) != 0) { 275 panic("idtpci_attach: failed to set up memory rman"); 276 } 277 278 sc->sc_irq_rman.rm_type = RMAN_ARRAY; 279 sc->sc_irq_rman.rm_descr = "IDTPCI PCI IRQs"; 280 if (rman_init(&sc->sc_irq_rman) != 0 || 281 rman_manage_region(&sc->sc_irq_rman, PCI_IRQ_BASE, 282 PCI_IRQ_END) != 0) 283 panic("idtpci_attach: failed to set up IRQ rman"); 284 285 device_add_child(dev, "pci", busno); 286 return (bus_generic_attach(dev)); 287} 288 289static int 290idtpci_maxslots(device_t dev) 291{ 292 293 return (PCI_SLOTMAX); 294} 295 296static uint32_t 297idtpci_read_config(device_t dev, int bus, int slot, int func, int reg, 298 int bytes) 299{ 300 uint32_t data; 301 uint32_t shift, mask; 302 bus_addr_t addr; 303 304 IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, 305 bus, slot, func, reg, bytes); 306 307 addr = idtpci_make_addr(bus, slot, func, reg); 308 309 REG_WRITE(IDT_PCI_CFG_ADDR, addr); 310 data = REG_READ(IDT_PCI_CFG_DATA); 311 312 switch (reg % 4) { 313 case 3: 314 shift = 24; 315 break; 316 case 2: 317 shift = 16; 318 break; 319 case 1: 320 shift = 8; 321 break; 322 default: 323 shift = 0; 324 break; 325 } 326 327 switch (bytes) { 328 case 1: 329 mask = 0xff; 330 data = (data >> shift) & mask; 331 break; 332 case 2: 333 mask = 0xffff; 334 if (reg % 4 == 0) 335 data = data & mask; 336 else 337 data = (data >> 16) & mask; 338 break; 339 case 4: 340 break; 341 default: 342 panic("%s: wrong bytes count", __func__); 343 break; 344 } 345 346 __asm__ volatile ("sync"); 347 IDTPCI_DPRINTF("%s: read 0x%x\n", __func__, data); 348 349 return (data); 350} 351 352static void 353idtpci_write_config(device_t dev, int bus, int slot, int func, int reg, 354 uint32_t data, int bytes) 355{ 356 bus_addr_t addr; 357 uint32_t reg_data; 358 uint32_t shift, mask; 359 360 IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d) data %08x\n", __func__, 361 bus, slot, func, reg, bytes, data); 362 363 if (bytes != 4) { 364 reg_data = idtpci_read_config(dev, bus, slot, func, reg, 4); 365 366 switch (reg % 4) { 367 case 3: 368 shift = 24; 369 break; 370 case 2: 371 shift = 16; 372 break; 373 case 1: 374 shift = 8; 375 break; 376 default: 377 shift = 0; 378 break; 379 } 380 381 switch (bytes) { 382 case 1: 383 mask = 0xff; 384 data = (reg_data & ~ (mask << shift)) | (data << shift); 385 break; 386 case 2: 387 mask = 0xffff; 388 if (reg % 4 == 0) 389 data = (reg_data & ~mask) | data; 390 else 391 data = (reg_data & ~ (mask << shift)) | 392 (data << shift); 393 break; 394 case 4: 395 break; 396 default: 397 panic("%s: wrong bytes count", __func__); 398 break; 399 } 400 } 401 402 addr = idtpci_make_addr(bus, slot, func, reg); 403 404 405 REG_WRITE(IDT_PCI_CFG_ADDR, addr); 406 REG_WRITE(IDT_PCI_CFG_DATA, data); 407 __asm__ volatile ("sync"); 408 409 REG_WRITE(IDT_PCI_CFG_ADDR, 0); 410 REG_WRITE(IDT_PCI_CFG_DATA, 0); 411} 412 413static int 414idtpci_route_interrupt(device_t pcib, device_t device, int pin) 415{ 416 static int idt_pci_table[2][12] = 417 { 418 { 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 }, 419 { 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 } 420 }; 421 int dev, bus, irq; 422 423 dev = pci_get_slot(device); 424 bus = pci_get_bus(device); 425 if (bootverbose) 426 device_printf(pcib, "routing pin %d for %s\n", pin, 427 device_get_nameunit(device)); 428 if (bus >= 0 && bus <= 1 && 429 dev >= 0 && dev <= 11) { 430 irq = IP_IRQ(6, idt_pci_table[bus][dev] + 4); 431 if (bootverbose) 432 printf("idtpci: %d/%d/%d -> IRQ%d\n", 433 pci_get_bus(device), dev, pci_get_function(device), 434 irq); 435 return (irq); 436 } else 437 printf("idtpci: no mapping for %d/%d/%d\n", 438 pci_get_bus(device), dev, pci_get_function(device)); 439 440 return (-1); 441} 442 443static int 444idtpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 445{ 446 struct idtpci_softc *sc = device_get_softc(dev); 447 448 switch (which) { 449 case PCIB_IVAR_DOMAIN: 450 *result = 0; 451 return (0); 452 case PCIB_IVAR_BUS: 453 *result = sc->sc_busno; 454 return (0); 455 } 456 457 return (ENOENT); 458} 459 460static int 461idtpci_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 462{ 463 struct idtpci_softc * sc = device_get_softc(dev); 464 465 switch (which) { 466 case PCIB_IVAR_BUS: 467 sc->sc_busno = result; 468 return (0); 469 } 470 return (ENOENT); 471} 472 473static struct resource * 474idtpci_alloc_resource(device_t bus, device_t child, int type, int *rid, 475 u_long start, u_long end, u_long count, u_int flags) 476{ 477 478 struct idtpci_softc *sc = device_get_softc(bus); 479 struct resource *rv = NULL; 480 struct rman *rm1, *rm2; 481 482 switch (type) { 483 case SYS_RES_IRQ: 484 rm1 = &sc->sc_irq_rman; 485 rm2 = NULL; 486 break; 487 case SYS_RES_MEMORY: 488 rm1 = &sc->sc_mem_rman[0]; 489 rm2 = &sc->sc_mem_rman[1]; 490 break; 491 case SYS_RES_IOPORT: 492 rm1 = &sc->sc_io_rman[0]; 493 rm2 = &sc->sc_io_rman[1]; 494 break; 495 default: 496 return (NULL); 497 } 498 499 rv = rman_reserve_resource(rm1, start, end, count, flags, child); 500 501 /* Try second window if it exists */ 502 if ((rv == NULL) && (rm2 != NULL)) 503 rv = rman_reserve_resource(rm2, start, end, count, flags, 504 child); 505 506 if (rv == NULL) 507 return (NULL); 508 509 rman_set_rid(rv, *rid); 510 511 if (flags & RF_ACTIVE) { 512 if (bus_activate_resource(child, type, *rid, rv)) { 513 rman_release_resource(rv); 514 return (NULL); 515 } 516 } 517 518 return (rv); 519} 520 521static int 522idtpci_teardown_intr(device_t dev, device_t child, struct resource *res, 523 void *cookie) 524{ 525 526 return (intr_event_remove_handler(cookie)); 527} 528 529static device_method_t idtpci_methods[] = { 530 /* Device interface */ 531 DEVMETHOD(device_probe, idtpci_probe), 532 DEVMETHOD(device_attach, idtpci_attach), 533 DEVMETHOD(device_shutdown, bus_generic_shutdown), 534 DEVMETHOD(device_suspend, bus_generic_suspend), 535 DEVMETHOD(device_resume, bus_generic_resume), 536 537 /* Bus interface */ 538 DEVMETHOD(bus_print_child, bus_generic_print_child), 539 DEVMETHOD(bus_read_ivar, idtpci_read_ivar), 540 DEVMETHOD(bus_write_ivar, idtpci_write_ivar), 541 DEVMETHOD(bus_alloc_resource, idtpci_alloc_resource), 542 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 543 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 544 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 545 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 546 DEVMETHOD(bus_teardown_intr, idtpci_teardown_intr), 547 548 /* pcib interface */ 549 DEVMETHOD(pcib_maxslots, idtpci_maxslots), 550 DEVMETHOD(pcib_read_config, idtpci_read_config), 551 DEVMETHOD(pcib_write_config, idtpci_write_config), 552 DEVMETHOD(pcib_route_interrupt, idtpci_route_interrupt), 553 554 {0, 0} 555}; 556 557static driver_t idtpci_driver = { 558 "pcib", 559 idtpci_methods, 560 sizeof(struct idtpci_softc), 561}; 562 563static devclass_t idtpci_devclass; 564 565DRIVER_MODULE(idtpci, obio, idtpci_driver, idtpci_devclass, 0, 0); 566