pchb.c revision 1.13 1 /* $NetBSD: pchb.c,v 1.13 2008/08/19 10:05:40 matthias 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.13 2008/08/19 10:05:40 matthias 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 <machine/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 #include "rnd.h"
53
54 #define PCISET_BRIDGETYPE_MASK 0x3
55 #define PCISET_TYPE_COMPAT 0x1
56 #define PCISET_TYPE_AUX 0x2
57
58 #define PCISET_BUSCONFIG_REG 0x48
59 #define PCISET_BRIDGE_NUMBER(reg) (((reg) >> 8) & 0xff)
60 #define PCISET_PCI_BUS_NUMBER(reg) (((reg) >> 16) & 0xff)
61
62 /* XXX should be in dev/ic/i82443reg.h */
63 #define I82443BX_SDRAMC_REG 0x74 /* upper 16 bits */
64
65 /* XXX should be in dev/ic/i82424{reg.var}.h */
66 #define I82424_CPU_BCTL_REG 0x53
67 #define I82424_PCI_BCTL_REG 0x54
68
69 #define I82424_BCTL_CPUMEM_POSTEN 0x01
70 #define I82424_BCTL_CPUPCI_POSTEN 0x02
71 #define I82424_BCTL_PCIMEM_BURSTEN 0x01
72 #define I82424_BCTL_PCI_BURSTEN 0x02
73
74 int pchbmatch(device_t, cfdata_t, void *);
75 void pchbattach(device_t, device_t, void *);
76 int pchbdetach(device_t, int);
77
78 static bool pchb_resume(device_t PMF_FN_ARGS);
79 static bool pchb_suspend(device_t PMF_FN_ARGS);
80
81 CFATTACH_DECL_NEW(pchb, sizeof(struct pchb_softc),
82 pchbmatch, pchbattach, pchbdetach, NULL);
83
84 int
85 pchbmatch(device_t parent, cfdata_t match, void *aux)
86 {
87 struct pci_attach_args *pa = aux;
88
89 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
90 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST)
91 return 1;
92
93 return 0;
94 }
95
96 int
97 pchb_get_bus_number(pci_chipset_tag_t pc, pcitag_t tag)
98 {
99 pcireg_t dev_id;
100 int bus, dev, func;
101 int bcreg, pbnum;
102
103 pci_decompose_tag(pc, tag, &bus, &dev, &func);
104
105 dev_id = pci_conf_read(pc, tag, PCI_ID_REG);
106 switch (PCI_VENDOR(dev_id)) {
107 case PCI_VENDOR_SERVERWORKS:
108 return pci_conf_read(pc, tag, 0x44) & 0xff;
109 case PCI_VENDOR_INTEL:
110 switch (PCI_PRODUCT(dev_id)) {
111 case PCI_PRODUCT_INTEL_82452_PB:
112 bcreg = pci_conf_read(pc, tag, 0x40);
113 pbnum = PCISET_BRIDGE_NUMBER(bcreg);
114 if (pbnum != 0xff)
115 return pbnum + 1;
116
117 break;
118 case PCI_PRODUCT_INTEL_PCI450_PB:
119 bcreg = pci_conf_read(pc, tag, PCISET_BUSCONFIG_REG);
120 return PCISET_PCI_BUS_NUMBER(bcreg);
121 case PCI_PRODUCT_INTEL_82451NX_PXB:
122 pbnum = 0;
123 switch (dev) {
124 case 18: /* PXB 0 bus A - primary bus */
125 break;
126 case 19: /* PXB 0 bus B */
127 /* read SUBA0 from MIOC */
128 tag = pci_make_tag(pc, 0, 16, 0);
129 bcreg = pci_conf_read(pc, tag, 0xd0);
130 pbnum = ((bcreg & 0x0000ff00) >> 8) + 1;
131 break;
132 case 20: /* PXB 1 bus A */
133 /* read BUSNO1 from MIOC */
134 tag = pci_make_tag(pc, 0, 16, 0);
135 bcreg = pci_conf_read(pc, tag, 0xd0);
136 pbnum = (bcreg & 0xff000000) >> 24;
137 break;
138 case 21: /* PXB 1 bus B */
139 /* read SUBA1 from MIOC */
140 tag = pci_make_tag(pc, 0, 16, 0);
141 bcreg = pci_conf_read(pc, tag, 0xd4);
142 pbnum = (bcreg & 0x000000ff) + 1;
143 break;
144 }
145 return pbnum;
146 }
147 }
148 return -1;
149 }
150
151 void
152 pchbattach(device_t parent, device_t self, void *aux)
153 {
154 struct pchb_softc *sc = device_private(self);
155 struct pci_attach_args *pa = aux;
156 char devinfo[256];
157 struct pcibus_attach_args pba;
158 struct agpbus_attach_args apa;
159 pcireg_t bcreg;
160 u_char bdnum, pbnum = 0; /* XXX: gcc */
161 pcitag_t tag;
162 int doattach, attachflags, has_agp;
163
164 aprint_naive("\n");
165 aprint_normal("\n");
166
167 doattach = 0;
168 has_agp = 0;
169 attachflags = pa->pa_flags;
170
171 sc->sc_dev = self;
172
173 /*
174 * Print out a description, and configure certain chipsets which
175 * have auxiliary PCI buses.
176 */
177
178 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
179 aprint_normal_dev(self, "%s (rev. 0x%02x)\n", devinfo,
180 PCI_REVISION(pa->pa_class));
181
182 switch (PCI_VENDOR(pa->pa_id)) {
183 /*
184 * i386 stuff.
185 */
186 case PCI_VENDOR_SERVERWORKS:
187 pbnum = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44) & 0xff;
188
189 if (pbnum == 0)
190 break;
191
192 /*
193 * This host bridge has a second PCI bus.
194 * Configure it.
195 */
196 switch (PCI_PRODUCT(pa->pa_id)) {
197 case PCI_PRODUCT_SERVERWORKS_CSB5:
198 case PCI_PRODUCT_SERVERWORKS_CSB6:
199 /* These devices show up as host bridges, but are
200 really southbridges. */
201 break;
202 case PCI_PRODUCT_SERVERWORKS_CMIC_HE:
203 case PCI_PRODUCT_SERVERWORKS_CMIC_LE:
204 case PCI_PRODUCT_SERVERWORKS_CMIC_SL:
205 /* CNBs and CIOBs are connected to these using a
206 private bus. The bus number register is that of
207 the first PCI bus hanging off the CIOB. We let
208 the CIOB attachment handle configuring the PCI
209 buses. */
210 break;
211 default:
212 aprint_error_dev(self,
213 "unknown ServerWorks chip ID 0x%04x; trying "
214 "to attach PCI buses behind it\n",
215 PCI_PRODUCT(pa->pa_id));
216 /* FALLTHROUGH */
217 case PCI_PRODUCT_SERVERWORKS_CNB20_LE_AGP:
218 case PCI_PRODUCT_SERVERWORKS_CNB30_LE_PCI:
219 case PCI_PRODUCT_SERVERWORKS_CNB20_LE_PCI:
220 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_PCI:
221 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_AGP:
222 case PCI_PRODUCT_SERVERWORKS_CIOB_X:
223 case PCI_PRODUCT_SERVERWORKS_CNB30_HE:
224 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_PCI2:
225 case PCI_PRODUCT_SERVERWORKS_CIOB_X2:
226 case PCI_PRODUCT_SERVERWORKS_CIOB_E:
227 switch (attachflags &
228 (PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED)) {
229 case 0:
230 /* Doesn't smell like there's anything there. */
231 break;
232 case PCI_FLAGS_MEM_ENABLED:
233 attachflags |= PCI_FLAGS_IO_ENABLED;
234 /* FALLTHROUGH */
235 default:
236 doattach = 1;
237 break;
238 }
239 break;
240 }
241 break;
242 case PCI_VENDOR_INTEL:
243 switch (PCI_PRODUCT(pa->pa_id)) {
244 case PCI_PRODUCT_INTEL_82452_PB:
245 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40);
246 pbnum = PCISET_BRIDGE_NUMBER(bcreg);
247 if (pbnum != 0xff) {
248 pbnum++;
249 doattach = 1;
250 }
251 break;
252 case PCI_PRODUCT_INTEL_82443BX_AGP:
253 case PCI_PRODUCT_INTEL_82443BX_NOAGP:
254 /*
255 * http://www.intel.com/design/chipsets/specupdt/290639.htm
256 * says this bug is fixed in steppings >= C0 (erratum 11),
257 * so don't tweak the bits in that case.
258 */
259 if (!(PCI_REVISION(pa->pa_class) >= 0x03)) {
260 /*
261 * BIOS BUG WORKAROUND! The 82443BX
262 * datasheet indicates that the only
263 * legal setting for the "Idle/Pipeline
264 * DRAM Leadoff Timing (IPLDT)" parameter
265 * (bits 9:8) is 01. Unfortunately, some
266 * BIOSs do not set these bits properly.
267 */
268 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag,
269 I82443BX_SDRAMC_REG);
270 if ((bcreg & 0x03000000) != 0x01000000) {
271 aprint_verbose_dev(self, "fixing "
272 "Idle/Pipeline DRAM "
273 "Leadoff Timing\n");
274 bcreg &= ~0x03000000;
275 bcreg |= 0x01000000;
276 pci_conf_write(pa->pa_pc, pa->pa_tag,
277 I82443BX_SDRAMC_REG, bcreg);
278 }
279 }
280 break;
281
282 case PCI_PRODUCT_INTEL_PCI450_PB:
283 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag,
284 PCISET_BUSCONFIG_REG);
285 bdnum = PCISET_BRIDGE_NUMBER(bcreg);
286 pbnum = PCISET_PCI_BUS_NUMBER(bcreg);
287 switch (bdnum & PCISET_BRIDGETYPE_MASK) {
288 default:
289 aprint_error_dev(self, "bdnum=%x (reserved)\n",
290 bdnum);
291 break;
292 case PCISET_TYPE_COMPAT:
293 aprint_verbose_dev(self,
294 "Compatibility PB (bus %d)\n", pbnum);
295 break;
296 case PCISET_TYPE_AUX:
297 aprint_verbose_dev(self,
298 "Auxiliary PB (bus %d)\n",pbnum);
299 /*
300 * This host bridge has a second PCI bus.
301 * Configure it.
302 */
303 doattach = 1;
304 break;
305 }
306 break;
307 case PCI_PRODUCT_INTEL_CDC:
308 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag,
309 I82424_CPU_BCTL_REG);
310 if (bcreg & I82424_BCTL_CPUPCI_POSTEN) {
311 bcreg &= ~I82424_BCTL_CPUPCI_POSTEN;
312 pci_conf_write(pa->pa_pc, pa->pa_tag,
313 I82424_CPU_BCTL_REG, bcreg);
314 aprint_verbose_dev(self,
315 "disabled CPU-PCI write posting\n");
316 }
317 break;
318 case PCI_PRODUCT_INTEL_82451NX_PXB:
319 /*
320 * The NX chipset supports up to 2 "PXB" chips
321 * which can drive 2 PCI buses each. Each bus
322 * shows up as logical PCI device, with fixed
323 * device numbers between 18 and 21.
324 * See the datasheet at
325 ftp://download.intel.com/design/chipsets/datashts/24377102.pdf
326 * for details.
327 * (It would be easier to attach all the buses
328 * at the MIOC, but less aesthetical imho.)
329 */
330 if ((attachflags &
331 (PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED)) ==
332 PCI_FLAGS_MEM_ENABLED)
333 attachflags |= PCI_FLAGS_IO_ENABLED;
334
335 pbnum = 0;
336 switch (pa->pa_device) {
337 case 18: /* PXB 0 bus A - primary bus */
338 break;
339 case 19: /* PXB 0 bus B */
340 /* read SUBA0 from MIOC */
341 tag = pci_make_tag(pa->pa_pc, 0, 16, 0);
342 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd0);
343 pbnum = ((bcreg & 0x0000ff00) >> 8) + 1;
344 break;
345 case 20: /* PXB 1 bus A */
346 /* read BUSNO1 from MIOC */
347 tag = pci_make_tag(pa->pa_pc, 0, 16, 0);
348 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd0);
349 pbnum = (bcreg & 0xff000000) >> 24;
350 break;
351 case 21: /* PXB 1 bus B */
352 /* read SUBA1 from MIOC */
353 tag = pci_make_tag(pa->pa_pc, 0, 16, 0);
354 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd4);
355 pbnum = (bcreg & 0x000000ff) + 1;
356 break;
357 }
358 if (pbnum != 0)
359 doattach = 1;
360 break;
361
362 /*
363 * i386 and amd64 stuff.
364 */
365 case PCI_PRODUCT_INTEL_82810_MCH:
366 case PCI_PRODUCT_INTEL_82810_DC100_MCH:
367 case PCI_PRODUCT_INTEL_82810E_MCH:
368 case PCI_PRODUCT_INTEL_82815_FULL_HUB:
369 case PCI_PRODUCT_INTEL_82830MP_IO_1:
370 case PCI_PRODUCT_INTEL_82845G_DRAM:
371 case PCI_PRODUCT_INTEL_82855GM_MCH:
372 case PCI_PRODUCT_INTEL_82865_HB:
373 case PCI_PRODUCT_INTEL_82915G_HB:
374 case PCI_PRODUCT_INTEL_82915GM_HB:
375 case PCI_PRODUCT_INTEL_82945P_MCH:
376 case PCI_PRODUCT_INTEL_82945GM_HB:
377 case PCI_PRODUCT_INTEL_82946GZ_HB:
378 case PCI_PRODUCT_INTEL_82965Q_HB:
379 case PCI_PRODUCT_INTEL_82965G_HB:
380 case PCI_PRODUCT_INTEL_82965PM_HB:
381 case PCI_PRODUCT_INTEL_82Q35_HB:
382 case PCI_PRODUCT_INTEL_82G33_HB:
383 case PCI_PRODUCT_INTEL_82Q33_HB:
384 /*
385 * The host bridge is either in GFX mode (internal
386 * graphics) or in AGP mode. In GFX mode, we pretend
387 * to have AGP because the graphics memory access
388 * is very similar and the AGP GATT code will
389 * deal with this. In the latter case, the
390 * pci_get_capability(PCI_CAP_AGP) test below will
391 * fire, so we do no harm by already setting the flag.
392 */
393 has_agp = 1;
394 break;
395 }
396 break;
397 }
398
399 #if NRND > 0
400 /*
401 * Attach a random number generator, if there is one.
402 */
403 pchb_attach_rnd(sc, pa);
404 #endif
405
406 if (!pmf_device_register(self, pchb_suspend, pchb_resume))
407 aprint_error_dev(self, "couldn't establish power handler\n");
408
409 /*
410 * If we haven't detected AGP yet (via a product ID),
411 * then check for AGP capability on the device.
412 */
413 if (has_agp ||
414 pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
415 NULL, NULL) != 0) {
416 apa.apa_pci_args = *pa;
417 config_found_ia(self, "agpbus", &apa, agpbusprint);
418 }
419
420 if (doattach) {
421 pba.pba_iot = pa->pa_iot;
422 pba.pba_memt = pa->pa_memt;
423 pba.pba_dmat = pa->pa_dmat;
424 pba.pba_dmat64 = pa->pa_dmat64;
425 pba.pba_pc = pa->pa_pc;
426 pba.pba_flags = attachflags;
427 pba.pba_bus = pbnum;
428 pba.pba_bridgetag = NULL;
429 pba.pba_pc = pa->pa_pc;
430 pba.pba_intrswiz = 0;
431 memset(&pba.pba_intrtag, 0, sizeof(pba.pba_intrtag));
432 config_found_ia(self, "pcibus", &pba, pcibusprint);
433 }
434 }
435
436 int
437 pchbdetach(device_t self, int flags)
438 {
439 int rc;
440 #if NRND > 0
441 struct pchb_softc *sc = device_private(self);
442 #endif
443
444 if ((rc = config_detach_children(self, flags)) != 0)
445 return rc;
446
447 pmf_device_deregister(self);
448
449 #if NRND > 0
450 /*
451 * Attach a random number generator, if there is one.
452 */
453 pchb_detach_rnd(sc);
454 #endif
455 return 0;
456 }
457
458 static bool
459 pchb_suspend(device_t dv PMF_FN_ARGS)
460 {
461 struct pchb_softc *sc = device_private(dv);
462 pci_chipset_tag_t pc;
463 pcitag_t tag;
464 int off;
465
466 pc = sc->sc_pc;
467 tag = sc->sc_tag;
468
469 for (off = 0x40; off <= 0xff; off += 4)
470 sc->sc_pciconfext[(off - 0x40) / 4] = pci_conf_read(pc, tag, off);
471
472 return true;
473 }
474
475 static bool
476 pchb_resume(device_t dv PMF_FN_ARGS)
477 {
478 struct pchb_softc *sc = device_private(dv);
479 pci_chipset_tag_t pc;
480 pcitag_t tag;
481 int off;
482
483 pc = sc->sc_pc;
484 tag = sc->sc_tag;
485
486 for (off = 0x40; off <= 0xff; off += 4)
487 pci_conf_write(pc, tag, off, sc->sc_pciconfext[(off - 0x40) / 4]);
488
489 return true;
490 }
491