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