1/* $NetBSD: pchb.c,v 1.32 2011/08/20 20:01:08 jakllsch Exp $ */ 2 3/*- 4 * Copyright (c) 1996, 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: pchb.c,v 1.32 2011/08/20 20:01:08 jakllsch Exp $"); 34 35#include <sys/types.h> 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/device.h> 39 40#include <sys/bus.h> 41 42#include <dev/pci/pcivar.h> 43#include <dev/pci/pcireg.h> 44 45#include <dev/pci/pcidevs.h> 46 47#include <dev/pci/agpreg.h> 48#include <dev/pci/agpvar.h> 49 50#include <arch/x86/pci/pchbvar.h> 51 52#define PCISET_BRIDGETYPE_MASK 0x3 53#define PCISET_TYPE_COMPAT 0x1 54#define PCISET_TYPE_AUX 0x2 55 56#define PCISET_BUSCONFIG_REG 0x48 57#define PCISET_BRIDGE_NUMBER(reg) (((reg) >> 8) & 0xff) 58#define PCISET_PCI_BUS_NUMBER(reg) (((reg) >> 16) & 0xff) 59 60/* XXX should be in dev/ic/i82443reg.h */ 61#define I82443BX_SDRAMC_REG 0x74 /* upper 16 bits */ 62 63/* XXX should be in dev/ic/i82424{reg.var}.h */ 64#define I82424_CPU_BCTL_REG 0x53 65#define I82424_PCI_BCTL_REG 0x54 66 67#define I82424_BCTL_CPUMEM_POSTEN 0x01 68#define I82424_BCTL_CPUPCI_POSTEN 0x02 69#define I82424_BCTL_PCIMEM_BURSTEN 0x01 70#define I82424_BCTL_PCI_BURSTEN 0x02 71 72static int pchbmatch(device_t, cfdata_t, void *); 73static void pchbattach(device_t, device_t, void *); 74static int pchbdetach(device_t, int); 75static int pchbrescan(device_t, const char *, const int *); 76static void pchbchilddet(device_t, device_t); 77 78static bool pchb_resume(device_t, const pmf_qual_t *); 79static bool pchb_suspend(device_t, const pmf_qual_t *); 80 81static void pchb_amdtempbus_configure(struct pchb_softc *); 82 83CFATTACH_DECL3_NEW(pchb, sizeof(struct pchb_softc), 84 pchbmatch, pchbattach, pchbdetach, NULL, pchbrescan, pchbchilddet, DVF_DETACH_SHUTDOWN); 85 86static int 87pchbmatch(device_t parent, cfdata_t match, void *aux) 88{ 89 struct pci_attach_args *pa = aux; 90 91 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 92 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST) 93 return 1; 94 95 return 0; 96} 97 98int 99pchb_get_bus_number(pci_chipset_tag_t pc, pcitag_t tag) 100{ 101 pcireg_t dev_id; 102 int bus, dev, func; 103 int bcreg, pbnum; 104 105 pci_decompose_tag(pc, tag, &bus, &dev, &func); 106 107 dev_id = pci_conf_read(pc, tag, PCI_ID_REG); 108 switch (PCI_VENDOR(dev_id)) { 109 case PCI_VENDOR_SERVERWORKS: 110 return pci_conf_read(pc, tag, 0x44) & 0xff; 111 case PCI_VENDOR_INTEL: 112 switch (PCI_PRODUCT(dev_id)) { 113 case PCI_PRODUCT_INTEL_82452_PB: 114 bcreg = pci_conf_read(pc, tag, 0x40); 115 pbnum = PCISET_BRIDGE_NUMBER(bcreg); 116 if (pbnum != 0xff) 117 return pbnum + 1; 118 119 break; 120 case PCI_PRODUCT_INTEL_PCI450_PB: 121 bcreg = pci_conf_read(pc, tag, PCISET_BUSCONFIG_REG); 122 return PCISET_PCI_BUS_NUMBER(bcreg); 123 case PCI_PRODUCT_INTEL_82451NX_PXB: 124 pbnum = 0; 125 switch (dev) { 126 case 18: /* PXB 0 bus A - primary bus */ 127 break; 128 case 19: /* PXB 0 bus B */ 129 /* read SUBA0 from MIOC */ 130 tag = pci_make_tag(pc, 0, 16, 0); 131 bcreg = pci_conf_read(pc, tag, 0xd0); 132 pbnum = ((bcreg & 0x0000ff00) >> 8) + 1; 133 break; 134 case 20: /* PXB 1 bus A */ 135 /* read BUSNO1 from MIOC */ 136 tag = pci_make_tag(pc, 0, 16, 0); 137 bcreg = pci_conf_read(pc, tag, 0xd0); 138 pbnum = (bcreg & 0xff000000) >> 24; 139 break; 140 case 21: /* PXB 1 bus B */ 141 /* read SUBA1 from MIOC */ 142 tag = pci_make_tag(pc, 0, 16, 0); 143 bcreg = pci_conf_read(pc, tag, 0xd4); 144 pbnum = (bcreg & 0x000000ff) + 1; 145 break; 146 } 147 return pbnum; 148 } 149 } 150 return -1; 151} 152 153static void 154pchbattach(device_t parent, device_t self, void *aux) 155{ 156 struct pchb_softc *sc = device_private(self); 157 const struct pci_attach_args *pa = aux; 158 struct pcibus_attach_args pba; 159 struct agpbus_attach_args apa; 160 pcireg_t bcreg; 161 u_char bdnum, pbnum = 0; /* XXX: gcc */ 162 pcitag_t tag; 163 int doattach, attachflags, has_agp; 164 165 doattach = 0; 166 has_agp = 0; 167 attachflags = pa->pa_flags; 168 169 sc->sc_dev = self; 170 sc->sc_pa = *pa; 171 172 /* 173 * Print out a description, and configure certain chipsets which 174 * have auxiliary PCI buses. 175 */ 176 177 pci_aprint_devinfo(pa, NULL); 178 179 switch (PCI_VENDOR(pa->pa_id)) { 180 /* 181 * i386 stuff. 182 */ 183 case PCI_VENDOR_SERVERWORKS: 184 pbnum = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44) & 0xff; 185 186 if (pbnum == 0) 187 break; 188 189 /* 190 * This host bridge has a second PCI bus. 191 * Configure it. 192 */ 193 switch (PCI_PRODUCT(pa->pa_id)) { 194 case PCI_PRODUCT_SERVERWORKS_CSB5: 195 case PCI_PRODUCT_SERVERWORKS_CSB6: 196 /* These devices show up as host bridges, but are 197 really southbridges. */ 198 break; 199 case PCI_PRODUCT_SERVERWORKS_CMIC_HE: 200 case PCI_PRODUCT_SERVERWORKS_CMIC_LE: 201 case PCI_PRODUCT_SERVERWORKS_CMIC_SL: 202 /* CNBs and CIOBs are connected to these using a 203 private bus. The bus number register is that of 204 the first PCI bus hanging off the CIOB. We let 205 the CIOB attachment handle configuring the PCI 206 buses. */ 207 break; 208 default: 209 aprint_error_dev(self, 210 "unknown ServerWorks chip ID 0x%04x; trying " 211 "to attach PCI buses behind it\n", 212 PCI_PRODUCT(pa->pa_id)); 213 /* FALLTHROUGH */ 214 case PCI_PRODUCT_SERVERWORKS_CNB20_LE_AGP: 215 case PCI_PRODUCT_SERVERWORKS_CNB30_LE_PCI: 216 case PCI_PRODUCT_SERVERWORKS_CNB20_LE_PCI: 217 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_PCI: 218 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_AGP: 219 case PCI_PRODUCT_SERVERWORKS_CIOB_X: 220 case PCI_PRODUCT_SERVERWORKS_CNB30_HE: 221 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_PCI2: 222 case PCI_PRODUCT_SERVERWORKS_CIOB_X2: 223 case PCI_PRODUCT_SERVERWORKS_CIOB_E: 224 switch (attachflags & 225 (PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY)) { 226 case 0: 227 /* Doesn't smell like there's anything there. */ 228 break; 229 case PCI_FLAGS_MEM_OKAY: 230 attachflags |= PCI_FLAGS_IO_OKAY; 231 /* FALLTHROUGH */ 232 default: 233 doattach = 1; 234 break; 235 } 236 break; 237 } 238 break; 239 case PCI_VENDOR_INTEL: 240 switch (PCI_PRODUCT(pa->pa_id)) { 241 case PCI_PRODUCT_INTEL_82452_PB: 242 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40); 243 pbnum = PCISET_BRIDGE_NUMBER(bcreg); 244 if (pbnum != 0xff) { 245 pbnum++; 246 doattach = 1; 247 } 248 break; 249 case PCI_PRODUCT_INTEL_82443BX_AGP: 250 case PCI_PRODUCT_INTEL_82443BX_NOAGP: 251 /* 252 * http://www.intel.com/design/chipsets/specupdt/290639.htm 253 * says this bug is fixed in steppings >= C0 (erratum 11), 254 * so don't tweak the bits in that case. 255 */ 256 if (!(PCI_REVISION(pa->pa_class) >= 0x03)) { 257 /* 258 * BIOS BUG WORKAROUND! The 82443BX 259 * datasheet indicates that the only 260 * legal setting for the "Idle/Pipeline 261 * DRAM Leadoff Timing (IPLDT)" parameter 262 * (bits 9:8) is 01. Unfortunately, some 263 * BIOSs do not set these bits properly. 264 */ 265 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 266 I82443BX_SDRAMC_REG); 267 if ((bcreg & 0x03000000) != 0x01000000) { 268 aprint_verbose_dev(self, "fixing " 269 "Idle/Pipeline DRAM " 270 "Leadoff Timing\n"); 271 bcreg &= ~0x03000000; 272 bcreg |= 0x01000000; 273 pci_conf_write(pa->pa_pc, pa->pa_tag, 274 I82443BX_SDRAMC_REG, bcreg); 275 } 276 } 277 break; 278 279 case PCI_PRODUCT_INTEL_PCI450_PB: 280 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 281 PCISET_BUSCONFIG_REG); 282 bdnum = PCISET_BRIDGE_NUMBER(bcreg); 283 pbnum = PCISET_PCI_BUS_NUMBER(bcreg); 284 switch (bdnum & PCISET_BRIDGETYPE_MASK) { 285 default: 286 aprint_error_dev(self, "bdnum=%x (reserved)\n", 287 bdnum); 288 break; 289 case PCISET_TYPE_COMPAT: 290 aprint_verbose_dev(self, 291 "Compatibility PB (bus %d)\n", pbnum); 292 break; 293 case PCISET_TYPE_AUX: 294 aprint_verbose_dev(self, 295 "Auxiliary PB (bus %d)\n",pbnum); 296 /* 297 * This host bridge has a second PCI bus. 298 * Configure it. 299 */ 300 doattach = 1; 301 break; 302 } 303 break; 304 case PCI_PRODUCT_INTEL_CDC: 305 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 306 I82424_CPU_BCTL_REG); 307 if (bcreg & I82424_BCTL_CPUPCI_POSTEN) { 308 bcreg &= ~I82424_BCTL_CPUPCI_POSTEN; 309 pci_conf_write(pa->pa_pc, pa->pa_tag, 310 I82424_CPU_BCTL_REG, bcreg); 311 aprint_verbose_dev(self, 312 "disabled CPU-PCI write posting\n"); 313 } 314 break; 315 case PCI_PRODUCT_INTEL_82451NX_PXB: 316 /* 317 * The NX chipset supports up to 2 "PXB" chips 318 * which can drive 2 PCI buses each. Each bus 319 * shows up as logical PCI device, with fixed 320 * device numbers between 18 and 21. 321 * See the datasheet at 322 ftp://download.intel.com/design/chipsets/datashts/24377102.pdf 323 * for details. 324 * (It would be easier to attach all the buses 325 * at the MIOC, but less aesthetical imho.) 326 */ 327 if ((attachflags & 328 (PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY)) == 329 PCI_FLAGS_MEM_OKAY) 330 attachflags |= PCI_FLAGS_IO_OKAY; 331 332 pbnum = 0; 333 switch (pa->pa_device) { 334 case 18: /* PXB 0 bus A - primary bus */ 335 break; 336 case 19: /* PXB 0 bus B */ 337 /* read SUBA0 from MIOC */ 338 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 339 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd0); 340 pbnum = ((bcreg & 0x0000ff00) >> 8) + 1; 341 break; 342 case 20: /* PXB 1 bus A */ 343 /* read BUSNO1 from MIOC */ 344 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 345 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd0); 346 pbnum = (bcreg & 0xff000000) >> 24; 347 break; 348 case 21: /* PXB 1 bus B */ 349 /* read SUBA1 from MIOC */ 350 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 351 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd4); 352 pbnum = (bcreg & 0x000000ff) + 1; 353 break; 354 } 355 if (pbnum != 0) 356 doattach = 1; 357 break; 358 359 /* 360 * i386 and amd64 stuff. 361 */ 362 case PCI_PRODUCT_INTEL_82810_MCH: 363 case PCI_PRODUCT_INTEL_82810_DC100_MCH: 364 case PCI_PRODUCT_INTEL_82810E_MCH: 365 case PCI_PRODUCT_INTEL_82815_FULL_HUB: 366 case PCI_PRODUCT_INTEL_82830MP_IO_1: 367 case PCI_PRODUCT_INTEL_82845G_DRAM: 368 case PCI_PRODUCT_INTEL_82855GM_MCH: 369 case PCI_PRODUCT_INTEL_82865_HB: 370 case PCI_PRODUCT_INTEL_82915G_HB: 371 case PCI_PRODUCT_INTEL_82915GM_HB: 372 case PCI_PRODUCT_INTEL_82945P_MCH: 373 case PCI_PRODUCT_INTEL_82945GM_HB: 374 case PCI_PRODUCT_INTEL_82945GME_HB: 375 case PCI_PRODUCT_INTEL_82946GZ_HB: 376 case PCI_PRODUCT_INTEL_82965Q_HB: 377 case PCI_PRODUCT_INTEL_82965G_HB: 378 case PCI_PRODUCT_INTEL_82965PM_HB: 379 case PCI_PRODUCT_INTEL_82Q35_HB: 380 case PCI_PRODUCT_INTEL_82G33_HB: 381 case PCI_PRODUCT_INTEL_82Q33_HB: 382 case PCI_PRODUCT_INTEL_82G35_HB: 383 case PCI_PRODUCT_INTEL_82GM45_HB: 384 case PCI_PRODUCT_INTEL_82IGD_E_HB: 385 case PCI_PRODUCT_INTEL_82Q45_HB: 386 case PCI_PRODUCT_INTEL_82G45_HB: 387 case PCI_PRODUCT_INTEL_82G41_HB: 388 case PCI_PRODUCT_INTEL_E7221_HB: 389 case PCI_PRODUCT_INTEL_82965GME_HB: 390 case PCI_PRODUCT_INTEL_82B43_HB: 391 case PCI_PRODUCT_INTEL_IRONLAKE_D_HB: 392 case PCI_PRODUCT_INTEL_IRONLAKE_M_HB: 393 case PCI_PRODUCT_INTEL_IRONLAKE_MA_HB: 394 case PCI_PRODUCT_INTEL_IRONLAKE_MC2_HB: 395 case PCI_PRODUCT_INTEL_PINEVIEW_HB: 396 case PCI_PRODUCT_INTEL_PINEVIEW_M_HB: 397 /* 398 * The host bridge is either in GFX mode (internal 399 * graphics) or in AGP mode. In GFX mode, we pretend 400 * to have AGP because the graphics memory access 401 * is very similar and the AGP GATT code will 402 * deal with this. In the latter case, the 403 * pci_get_capability(PCI_CAP_AGP) test below will 404 * fire, so we do no harm by already setting the flag. 405 */ 406 has_agp = 1; 407 break; 408 } 409 break; 410 } 411 412 if (!pmf_device_register(self, pchb_suspend, pchb_resume)) 413 aprint_error_dev(self, "couldn't establish power handler\n"); 414 415 /* 416 * If we haven't detected AGP yet (via a product ID), 417 * then check for AGP capability on the device. 418 */ 419 if (has_agp || 420 pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, 421 NULL, NULL) != 0) { 422 apa.apa_pci_args = *pa; 423 config_found_ia(self, "agpbus", &apa, agpbusprint); 424 } 425 426 if (doattach) { 427 pba.pba_iot = pa->pa_iot; 428 pba.pba_memt = pa->pa_memt; 429 pba.pba_dmat = pa->pa_dmat; 430 pba.pba_dmat64 = pa->pa_dmat64; 431 pba.pba_pc = pa->pa_pc; 432 pba.pba_flags = attachflags; 433 pba.pba_bus = pbnum; 434 pba.pba_bridgetag = NULL; 435 pba.pba_pc = pa->pa_pc; 436 pba.pba_intrswiz = 0; 437 memset(&pba.pba_intrtag, 0, sizeof(pba.pba_intrtag)); 438 config_found_ia(self, "pcibus", &pba, pcibusprint); 439 } 440 441 pchb_amdtempbus_configure(sc); 442} 443 444static int 445pchbdetach(device_t self, int flags) 446{ 447 int rc; 448 449 if ((rc = config_detach_children(self, flags)) != 0) 450 return rc; 451 452 pmf_device_deregister(self); 453 454 return 0; 455} 456 457static int 458pchbrescan(device_t self, const char *ifattr, const int *locators) 459{ 460 struct pchb_softc *sc = device_private(self); 461 462 if (ifattr_match(ifattr, "amdtempbus")) 463 pchb_amdtempbus_configure(sc); 464 465 return 0; 466} 467 468static void 469pchbchilddet(device_t self, device_t child) 470{ 471 struct pchb_softc *sc = device_private(self); 472 473 if (sc->sc_amdtempbus == child) { 474 sc->sc_amdtempbus = NULL; 475 return; 476 } 477} 478 479static bool 480pchb_suspend(device_t dv, const pmf_qual_t *qual) 481{ 482 struct pchb_softc *sc = device_private(dv); 483 pci_chipset_tag_t pc; 484 pcitag_t tag; 485 int off; 486 487 pc = sc->sc_pa.pa_pc; 488 tag = sc->sc_pa.pa_tag; 489 490 for (off = 0x40; off <= 0xff; off += 4) 491 sc->sc_pciconfext[(off - 0x40) / 4] = pci_conf_read(pc, tag, off); 492 493 return true; 494} 495 496static bool 497pchb_resume(device_t dv, const pmf_qual_t *qual) 498{ 499 struct pchb_softc *sc = device_private(dv); 500 pci_chipset_tag_t pc; 501 pcitag_t tag; 502 int off; 503 504 pc = sc->sc_pa.pa_pc; 505 tag = sc->sc_pa.pa_tag; 506 507 for (off = 0x40; off <= 0xff; off += 4) 508 pci_conf_write(pc, tag, off, sc->sc_pciconfext[(off - 0x40) / 4]); 509 510 return true; 511} 512 513static void 514pchb_amdtempbus_configure(struct pchb_softc *sc) 515{ 516 if (sc->sc_amdtempbus != NULL) 517 return; 518 519 sc->sc_amdtempbus = config_found_ia(sc->sc_dev, "amdtempbus", &sc->sc_pa, NULL); 520} 521