xref: /netbsd-src/sys/arch/x86/pci/pchb.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: pchb.c,v 1.5 2007/12/09 20:27:49 jmcneill 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.5 2007/12/09 20:27:49 jmcneill 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	0x76
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(struct device *, struct cfdata *, void *);
82 void	pchbattach(struct device *, struct device *, void *);
83 
84 static bool	pchb_resume(device_t);
85 static bool	pchb_suspend(device_t);
86 
87 CFATTACH_DECL(pchb, sizeof(struct pchb_softc),
88     pchbmatch, pchbattach, NULL, NULL);
89 
90 int
91 pchbmatch(struct device *parent, struct cfdata *match, void *aux)
92 {
93 	struct pci_attach_args *pa = aux;
94 
95 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
96 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST)
97 		return 1;
98 
99 	return 0;
100 }
101 
102 void
103 pchbattach(struct device *parent, struct device *self, void *aux)
104 {
105 #if NRND > 0
106 	struct pchb_softc *sc = (void *) self;
107 #endif
108 	struct pci_attach_args *pa = aux;
109 	char devinfo[256];
110 	struct pcibus_attach_args pba;
111 	struct agpbus_attach_args apa;
112 	pcireg_t bcreg;
113 	u_char bdnum, pbnum = 0; /* XXX: gcc */
114 	pcitag_t tag;
115 	int doattach, attachflags, has_agp;
116 
117 	aprint_naive("\n");
118 	aprint_normal("\n");
119 
120 	doattach = 0;
121 	has_agp = 0;
122 	attachflags = pa->pa_flags;
123 
124 	/*
125 	 * Print out a description, and configure certain chipsets which
126 	 * have auxiliary PCI buses.
127 	 */
128 
129 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
130 	aprint_normal("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo,
131 	    PCI_REVISION(pa->pa_class));
132 
133 	switch (PCI_VENDOR(pa->pa_id)) {
134 	/*
135 	 * i386 stuff.
136 	 */
137 	case PCI_VENDOR_SERVERWORKS:
138 		pbnum = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44) & 0xff;
139 
140 		if (pbnum == 0)
141 			break;
142 
143 		/*
144 		 * This host bridge has a second PCI bus.
145 		 * Configure it.
146 		 */
147 		switch (PCI_PRODUCT(pa->pa_id)) {
148 		case PCI_PRODUCT_SERVERWORKS_CSB5:
149 		case PCI_PRODUCT_SERVERWORKS_CSB6:
150 			/* These devices show up as host bridges, but are
151 			   really southbridges. */
152 			break;
153 		case PCI_PRODUCT_SERVERWORKS_CMIC_HE:
154 		case PCI_PRODUCT_SERVERWORKS_CMIC_LE:
155 		case PCI_PRODUCT_SERVERWORKS_CMIC_SL:
156 			/* CNBs and CIOBs are connected to these using a
157 			   private bus.  The bus number register is that of
158 			   the first PCI bus hanging off the CIOB.  We let
159 			   the CIOB attachment handle configuring the PCI
160 			   buses. */
161 			break;
162 		default:
163 			aprint_error("%s: unknown ServerWorks chip ID "
164 			    "0x%04x; trying to attach PCI buses behind it\n",
165 			    self->dv_xname, PCI_PRODUCT(pa->pa_id));
166 			/* FALLTHROUGH */
167 		case PCI_PRODUCT_SERVERWORKS_CNB20_LE_AGP:
168 		case PCI_PRODUCT_SERVERWORKS_CNB30_LE_PCI:
169 		case PCI_PRODUCT_SERVERWORKS_CNB20_LE_PCI:
170 		case PCI_PRODUCT_SERVERWORKS_CNB20_HE_PCI:
171 		case PCI_PRODUCT_SERVERWORKS_CNB20_HE_AGP:
172 		case PCI_PRODUCT_SERVERWORKS_CIOB_X:
173 		case PCI_PRODUCT_SERVERWORKS_CNB30_HE:
174 		case PCI_PRODUCT_SERVERWORKS_CNB20_HE_PCI2:
175 		case PCI_PRODUCT_SERVERWORKS_CIOB_X2:
176 		case PCI_PRODUCT_SERVERWORKS_CIOB_E:
177 			switch (attachflags &
178 			    (PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED)) {
179 			case 0:
180 				/* Doesn't smell like there's anything there. */
181 				break;
182 			case PCI_FLAGS_MEM_ENABLED:
183 				attachflags |= PCI_FLAGS_IO_ENABLED;
184 				/* FALLTHROUGH */
185 			default:
186 				doattach = 1;
187 				break;
188 			}
189 			break;
190 		}
191 		break;
192 	case PCI_VENDOR_INTEL:
193 		switch (PCI_PRODUCT(pa->pa_id)) {
194 		case PCI_PRODUCT_INTEL_82452_PB:
195 			bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40);
196 			pbnum = PCISET_BRIDGE_NUMBER(bcreg);
197 			if (pbnum != 0xff) {
198 				pbnum++;
199 				doattach = 1;
200 			}
201 			break;
202 		case PCI_PRODUCT_INTEL_82443BX_AGP:
203 		case PCI_PRODUCT_INTEL_82443BX_NOAGP:
204 		/*
205 		 * http://www.intel.com/design/chipsets/specupdt/290639.htm
206 		 * says this bug is fixed in steppings >= C0 (erratum 11),
207 		 * so don't tweak the bits in that case.
208 		 */
209 			if (!(PCI_REVISION(pa->pa_class) >= 0x03)) {
210 				/*
211 				 * BIOS BUG WORKAROUND!  The 82443BX
212 				 * datasheet indicates that the only
213 				 * legal setting for the "Idle/Pipeline
214 				 * DRAM Leadoff Timing (IPLDT)" parameter
215 				 * (bits 9:8) is 01.  Unfortunately, some
216 				 * BIOSs do not set these bits properly.
217 				 */
218 				bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag,
219 				    I82443BX_SDRAMC_REG);
220 				if ((bcreg & 0x0300) != 0x0100) {
221 					aprint_verbose("%s: fixing "
222 					    "Idle/Pipeline DRAM "
223 					    "Leadoff Timing\n", self->dv_xname);
224 					bcreg &= ~0x0300;
225 					bcreg |=  0x0100;
226 					pci_conf_write(pa->pa_pc, pa->pa_tag,
227 					    I82443BX_SDRAMC_REG, bcreg);
228 				}
229 			}
230 			break;
231 
232 		case PCI_PRODUCT_INTEL_PCI450_PB:
233 			bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag,
234 					      PCISET_BUSCONFIG_REG);
235 			bdnum = PCISET_BRIDGE_NUMBER(bcreg);
236 			pbnum = PCISET_PCI_BUS_NUMBER(bcreg);
237 			switch (bdnum & PCISET_BRIDGETYPE_MASK) {
238 			default:
239 				aprint_error("%s: bdnum=%x (reserved)\n",
240 				       self->dv_xname, bdnum);
241 				break;
242 			case PCISET_TYPE_COMPAT:
243 				aprint_verbose(
244 				    "%s: Compatibility PB (bus %d)\n",
245 				    self->dv_xname, pbnum);
246 				break;
247 			case PCISET_TYPE_AUX:
248 				aprint_verbose("%s: Auxiliary PB (bus %d)\n",
249 				       self->dv_xname, pbnum);
250 				/*
251 				 * This host bridge has a second PCI bus.
252 				 * Configure it.
253 				 */
254 				doattach = 1;
255 				break;
256 			}
257 			break;
258 		case PCI_PRODUCT_INTEL_CDC:
259 			bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag,
260 					      I82424_CPU_BCTL_REG);
261 			if (bcreg & I82424_BCTL_CPUPCI_POSTEN) {
262 				bcreg &= ~I82424_BCTL_CPUPCI_POSTEN;
263 				pci_conf_write(pa->pa_pc, pa->pa_tag,
264 					       I82424_CPU_BCTL_REG, bcreg);
265 				aprint_verbose(
266 				    "%s: disabled CPU-PCI write posting\n",
267 				    self->dv_xname);
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 static bool
388 pchb_suspend(device_t dv)
389 {
390 	struct pchb_softc *sc = device_private(dv);
391 	pci_chipset_tag_t pc;
392 	pcitag_t tag;
393 	int off;
394 
395 	pc = sc->sc_pc;
396 	tag = sc->sc_tag;
397 
398 	for (off = 0x40; off <= 0xff; off += 4)
399 		sc->sc_pciconfext[(off - 0x40) / 4] = pci_conf_read(pc, tag, off);
400 
401 	return true;
402 }
403 
404 static bool
405 pchb_resume(device_t dv)
406 {
407 	struct pchb_softc *sc = device_private(dv);
408 	pci_chipset_tag_t pc;
409 	pcitag_t tag;
410 	int off;
411 
412 	pc = sc->sc_pc;
413 	tag = sc->sc_tag;
414 
415 	for (off = 0x40; off <= 0xff; off += 4)
416 		pci_conf_write(pc, tag, off, sc->sc_pciconfext[(off - 0x40) / 4]);
417 
418 	return true;
419 }
420