14d28e78fSSepherosa Ziehau /*-
24d28e78fSSepherosa Ziehau * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier
34d28e78fSSepherosa Ziehau * Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
44d28e78fSSepherosa Ziehau * Copyright (c) 2000 BSDi
54d28e78fSSepherosa Ziehau * All rights reserved.
64d28e78fSSepherosa Ziehau *
74d28e78fSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without
84d28e78fSSepherosa Ziehau * modification, are permitted provided that the following conditions
94d28e78fSSepherosa Ziehau * are met:
104d28e78fSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright
114d28e78fSSepherosa Ziehau * notice, this list of conditions and the following disclaimer.
124d28e78fSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright
134d28e78fSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the
144d28e78fSSepherosa Ziehau * documentation and/or other materials provided with the distribution.
154d28e78fSSepherosa Ziehau * 3. The name of the author may not be used to endorse or promote products
164d28e78fSSepherosa Ziehau * derived from this software without specific prior written permission.
174d28e78fSSepherosa Ziehau *
184d28e78fSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
194d28e78fSSepherosa Ziehau * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
204d28e78fSSepherosa Ziehau * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
214d28e78fSSepherosa Ziehau * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
224d28e78fSSepherosa Ziehau * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
234d28e78fSSepherosa Ziehau * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
244d28e78fSSepherosa Ziehau * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
254d28e78fSSepherosa Ziehau * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
264d28e78fSSepherosa Ziehau * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
274d28e78fSSepherosa Ziehau * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
284d28e78fSSepherosa Ziehau * SUCH DAMAGE.
2983c1faaaSSascha Wildner *
3083c1faaaSSascha Wildner * $FreeBSD: src/sys/dev/pci/fixup_pci.c,v 1.7.8.1 2009/04/15 03:14:26 kensmith Exp $
314d28e78fSSepherosa Ziehau */
324d28e78fSSepherosa Ziehau
334d28e78fSSepherosa Ziehau #include <sys/param.h>
344d28e78fSSepherosa Ziehau #include <sys/kernel.h>
354d28e78fSSepherosa Ziehau #include <sys/malloc.h>
364d28e78fSSepherosa Ziehau #include <sys/module.h>
374d28e78fSSepherosa Ziehau #include <sys/systm.h>
384d28e78fSSepherosa Ziehau #include <sys/bus.h>
394d28e78fSSepherosa Ziehau #include <sys/types.h>
404d28e78fSSepherosa Ziehau
414d28e78fSSepherosa Ziehau #include <bus/pci/pcivar.h>
424d28e78fSSepherosa Ziehau #include <bus/pci/pcireg.h>
434d28e78fSSepherosa Ziehau
444d28e78fSSepherosa Ziehau /*
454d28e78fSSepherosa Ziehau * Chipset fixups.
464d28e78fSSepherosa Ziehau *
474d28e78fSSepherosa Ziehau * These routines are invoked during the probe phase for devices which
484d28e78fSSepherosa Ziehau * typically don't have specific device drivers, but which require
494d28e78fSSepherosa Ziehau * some cleaning up.
504d28e78fSSepherosa Ziehau */
514d28e78fSSepherosa Ziehau
524d28e78fSSepherosa Ziehau static int fixup_pci_probe(device_t dev);
534d28e78fSSepherosa Ziehau static void fixwsc_natoma(device_t dev);
544d28e78fSSepherosa Ziehau static void fixc1_nforce2(device_t dev);
554d28e78fSSepherosa Ziehau
564d28e78fSSepherosa Ziehau static device_method_t fixup_pci_methods[] = {
574d28e78fSSepherosa Ziehau /* Device interface */
584d28e78fSSepherosa Ziehau DEVMETHOD(device_probe, fixup_pci_probe),
594d28e78fSSepherosa Ziehau DEVMETHOD(device_attach, bus_generic_attach),
60*d3c9c58eSSascha Wildner DEVMETHOD_END
614d28e78fSSepherosa Ziehau };
624d28e78fSSepherosa Ziehau
634d28e78fSSepherosa Ziehau static driver_t fixup_pci_driver = {
644d28e78fSSepherosa Ziehau "fixup_pci",
654d28e78fSSepherosa Ziehau fixup_pci_methods,
664d28e78fSSepherosa Ziehau 0,
674d28e78fSSepherosa Ziehau };
684d28e78fSSepherosa Ziehau
694d28e78fSSepherosa Ziehau static devclass_t fixup_pci_devclass;
704d28e78fSSepherosa Ziehau
71aa2b9d05SSascha Wildner DRIVER_MODULE(fixup_pci, pci, fixup_pci_driver, fixup_pci_devclass, NULL, NULL);
724d28e78fSSepherosa Ziehau
734d28e78fSSepherosa Ziehau static int
fixup_pci_probe(device_t dev)744d28e78fSSepherosa Ziehau fixup_pci_probe(device_t dev)
754d28e78fSSepherosa Ziehau {
764d28e78fSSepherosa Ziehau switch (pci_get_devid(dev)) {
774d28e78fSSepherosa Ziehau case 0x12378086: /* Intel 82440FX (Natoma) */
784d28e78fSSepherosa Ziehau fixwsc_natoma(dev);
794d28e78fSSepherosa Ziehau break;
804d28e78fSSepherosa Ziehau case 0x01e010de: /* nVidia nForce2 */
814d28e78fSSepherosa Ziehau fixc1_nforce2(dev);
824d28e78fSSepherosa Ziehau break;
834d28e78fSSepherosa Ziehau }
844d28e78fSSepherosa Ziehau return(ENXIO);
854d28e78fSSepherosa Ziehau }
864d28e78fSSepherosa Ziehau
874d28e78fSSepherosa Ziehau static void
fixwsc_natoma(device_t dev)884d28e78fSSepherosa Ziehau fixwsc_natoma(device_t dev)
894d28e78fSSepherosa Ziehau {
904d28e78fSSepherosa Ziehau int pmccfg;
914d28e78fSSepherosa Ziehau
924d28e78fSSepherosa Ziehau pmccfg = pci_read_config(dev, 0x50, 2);
934d28e78fSSepherosa Ziehau if (pmccfg & 0x8000) {
944d28e78fSSepherosa Ziehau kprintf("Correcting Natoma config for SMP\n");
954d28e78fSSepherosa Ziehau pmccfg &= ~0x8000;
964d28e78fSSepherosa Ziehau pci_write_config(dev, 0x50, pmccfg, 2);
974d28e78fSSepherosa Ziehau }
984d28e78fSSepherosa Ziehau }
994d28e78fSSepherosa Ziehau
1004d28e78fSSepherosa Ziehau /*
1014d28e78fSSepherosa Ziehau * Set the SYSTEM_IDLE_TIMEOUT to 80 ns on nForce2 systems to work
1024d28e78fSSepherosa Ziehau * around a hang that is triggered when the CPU generates a very fast
1034d28e78fSSepherosa Ziehau * CONNECT/HALT cycle sequence. Specifically, the hang can result in
1044d28e78fSSepherosa Ziehau * the lapic timer being stopped.
1054d28e78fSSepherosa Ziehau *
1064d28e78fSSepherosa Ziehau * This requires changing the value for config register at offset 0x6c
1074d28e78fSSepherosa Ziehau * for the Host-PCI bridge at bus/dev/function 0/0/0:
1084d28e78fSSepherosa Ziehau *
1094d28e78fSSepherosa Ziehau * Chip Current Value New Value
1104d28e78fSSepherosa Ziehau * ---- ---------- ----------
1114d28e78fSSepherosa Ziehau * C17 0x1F0FFF01 0x1F01FF01
1124d28e78fSSepherosa Ziehau * C18D 0x9F0FFF01 0x9F01FF01
1134d28e78fSSepherosa Ziehau *
1144d28e78fSSepherosa Ziehau * We do this by always clearing the bits in 0x000e0000.
1154d28e78fSSepherosa Ziehau *
1164d28e78fSSepherosa Ziehau * See also: http://lkml.org/lkml/2004/5/3/157
1174d28e78fSSepherosa Ziehau */
1184d28e78fSSepherosa Ziehau static void
fixc1_nforce2(device_t dev)1194d28e78fSSepherosa Ziehau fixc1_nforce2(device_t dev)
1204d28e78fSSepherosa Ziehau {
1214d28e78fSSepherosa Ziehau uint32_t val;
1224d28e78fSSepherosa Ziehau
1234d28e78fSSepherosa Ziehau if (pci_get_bus(dev) == 0 && pci_get_slot(dev) == 0 &&
1244d28e78fSSepherosa Ziehau pci_get_function(dev) == 0) {
1254d28e78fSSepherosa Ziehau val = pci_read_config(dev, 0x6c, 4);
1264d28e78fSSepherosa Ziehau if (val & 0x000e0000) {
1274d28e78fSSepherosa Ziehau kprintf("Correcting nForce2 C1 CPU disconnect hangs\n");
1284d28e78fSSepherosa Ziehau val &= ~0x000e0000;
1294d28e78fSSepherosa Ziehau pci_write_config(dev, 0x6c, val, 4);
1304d28e78fSSepherosa Ziehau }
1314d28e78fSSepherosa Ziehau }
1324d28e78fSSepherosa Ziehau }
133