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