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