pcib.c revision 1.4
11.4Smatt/*	$NetBSD: pcib.c,v 1.4 2008/04/04 16:04:19 matt Exp $	*/
21.2Sgarbled
31.2Sgarbled/*-
41.2Sgarbled * Copyright (c) 1996, 1998 The NetBSD Foundation, Inc.
51.2Sgarbled * All rights reserved.
61.2Sgarbled *
71.2Sgarbled * This code is derived from software contributed to The NetBSD Foundation
81.2Sgarbled * by Jason R. Thorpe.
91.2Sgarbled *
101.2Sgarbled * Redistribution and use in source and binary forms, with or without
111.2Sgarbled * modification, are permitted provided that the following conditions
121.2Sgarbled * are met:
131.2Sgarbled * 1. Redistributions of source code must retain the above copyright
141.2Sgarbled *    notice, this list of conditions and the following disclaimer.
151.2Sgarbled * 2. Redistributions in binary form must reproduce the above copyright
161.2Sgarbled *    notice, this list of conditions and the following disclaimer in the
171.2Sgarbled *    documentation and/or other materials provided with the distribution.
181.2Sgarbled * 3. All advertising materials mentioning features or use of this software
191.2Sgarbled *    must display the following acknowledgement:
201.2Sgarbled *        This product includes software developed by the NetBSD
211.2Sgarbled *        Foundation, Inc. and its contributors.
221.2Sgarbled * 4. Neither the name of The NetBSD Foundation nor the names of its
231.2Sgarbled *    contributors may be used to endorse or promote products derived
241.2Sgarbled *    from this software without specific prior written permission.
251.2Sgarbled *
261.2Sgarbled * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
271.2Sgarbled * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
281.2Sgarbled * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
291.2Sgarbled * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
301.2Sgarbled * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
311.2Sgarbled * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
321.2Sgarbled * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
331.2Sgarbled * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
341.2Sgarbled * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
351.2Sgarbled * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
361.2Sgarbled * POSSIBILITY OF SUCH DAMAGE.
371.2Sgarbled */
381.2Sgarbled
391.2Sgarbled#include <sys/cdefs.h>
401.4Smatt__KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.4 2008/04/04 16:04:19 matt Exp $");
411.2Sgarbled
421.2Sgarbled#include <sys/types.h>
431.2Sgarbled#include <sys/param.h>
441.2Sgarbled#include <sys/systm.h>
451.2Sgarbled#include <sys/device.h>
461.2Sgarbled
471.2Sgarbled#include <machine/bus.h>
481.2Sgarbled
491.2Sgarbled#include <dev/isa/isavar.h>
501.2Sgarbled
511.2Sgarbled#include <dev/pci/pcivar.h>
521.2Sgarbled#include <dev/pci/pcireg.h>
531.2Sgarbled
541.2Sgarbled#include <dev/pci/pcidevs.h>
551.2Sgarbled
561.2Sgarbled#include "isa.h"
571.2Sgarbled#include "isadma.h"
581.2Sgarbled
591.4Smattint	pcibmatch(device_t, cfdata_t, void *);
601.4Smattvoid	pcibattach(device_t, device_t, void *);
611.2Sgarbled
621.2Sgarbledstruct pcib_softc {
631.4Smatt	device_t sc_dev;
641.2Sgarbled	struct powerpc_isa_chipset *sc_chipset;
651.2Sgarbled};
661.2Sgarbled
671.2Sgarbledextern struct powerpc_isa_chipset genppc_ict;
681.2Sgarbledextern struct genppc_pci_chipset *genppc_pct;
691.2Sgarbled
701.4SmattCFATTACH_DECL_NEW(pcib, sizeof(struct pcib_softc),
711.2Sgarbled    pcibmatch, pcibattach, NULL, NULL);
721.2Sgarbled
731.4Smattvoid	pcib_callback(device_t);
741.2Sgarbled
751.2Sgarbledint
761.4Smattpcibmatch(device_t parent, cfdata_t cf, void *aux)
771.2Sgarbled{
781.2Sgarbled	struct pci_attach_args *pa = aux;
791.2Sgarbled
801.2Sgarbled	/*
811.2Sgarbled	 * Match PCI-ISA bridge.
821.2Sgarbled	 */
831.2Sgarbled	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
841.2Sgarbled	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) {
851.2Sgarbled		return (1);
861.2Sgarbled	}
871.2Sgarbled
881.2Sgarbled	/*
891.2Sgarbled	 * some special cases:
901.2Sgarbled	 */
911.2Sgarbled	switch (PCI_VENDOR(pa->pa_id)) {
921.2Sgarbled	case PCI_VENDOR_INTEL:
931.2Sgarbled		switch (PCI_PRODUCT(pa->pa_id)) {
941.2Sgarbled		case PCI_PRODUCT_INTEL_SIO:
951.2Sgarbled			/*
961.2Sgarbled			 * The Intel SIO identifies itself as a
971.2Sgarbled			 * miscellaneous prehistoric.
981.2Sgarbled			 */
991.2Sgarbled			return (1);
1001.2Sgarbled		}
1011.2Sgarbled		break;
1021.2Sgarbled	}
1031.2Sgarbled
1041.2Sgarbled	return (0);
1051.2Sgarbled}
1061.2Sgarbled
1071.2Sgarbledvoid
1081.4Smattpcibattach(device_t parent, device_t self, void *aux)
1091.2Sgarbled{
1101.2Sgarbled	struct pci_attach_args *pa = aux;
1111.4Smatt	struct pcib_softc *sc = device_private(self);
1121.2Sgarbled	char devinfo[256];
1131.2Sgarbled	u_int32_t v;
1141.2Sgarbled	int lvlmask = 0;
1151.2Sgarbled#ifdef prep
1161.2Sgarbled	prop_bool_t rav;
1171.2Sgarbled#endif
1181.2Sgarbled
1191.4Smatt	sc->sc_dev = self;
1201.4Smatt
1211.2Sgarbled	/*
1221.2Sgarbled	 * Just print out a description and defer configuration
1231.2Sgarbled	 * until all PCI devices have been attached.
1241.2Sgarbled	 */
1251.2Sgarbled	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
1261.2Sgarbled	aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
1271.2Sgarbled	    PCI_REVISION(pa->pa_class));
1281.2Sgarbled
1291.2Sgarbled	v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40);
1301.2Sgarbled	if ((v & 0x20) == 0) {
1311.2Sgarbled		aprint_verbose("%s: PIRQ[0-3] not used\n", self->dv_xname);
1321.2Sgarbled	} else {
1331.2Sgarbled		v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x60);
1341.2Sgarbled		if ((v & 0x80808080) == 0x80808080) {
1351.2Sgarbled			aprint_verbose("%s: PIRQ[0-3] disabled\n",
1361.2Sgarbled			    self->dv_xname);
1371.2Sgarbled		} else {
1381.2Sgarbled			int i;
1391.4Smatt			aprint_verbose("%s:", device_xname(self));
1401.2Sgarbled			for (i = 0; i < 4; i++, v >>= 8) {
1411.2Sgarbled				if ((v & 0x80) == 0 && (v & 0x0f) != 0) {
1421.2Sgarbled					aprint_verbose(" PIRQ[%d]=%d", i,
1431.2Sgarbled					    v & 0x0f);
1441.2Sgarbled					lvlmask |= (1 << (v & 0x0f));
1451.2Sgarbled				}
1461.2Sgarbled			}
1471.2Sgarbled			aprint_verbose("\n");
1481.2Sgarbled		}
1491.2Sgarbled	}
1501.2Sgarbled
1511.2Sgarbled	/*
1521.2Sgarbled	 * If we have an 83C553F-G sitting on a RAVEN host bridge,
1531.2Sgarbled	 * then we need to rewire some interrupts.
1541.2Sgarbled	 * The IDE Interrupt Routing Control Register lives at 0x43,
1551.2Sgarbled	 * and defaults to 0xEF, which means the primary controller
1561.2Sgarbled	 * interrupts on ivr-14, and the secondary on ivr-15. We
1571.2Sgarbled	 * reset it to 0xEE to fire them both at ivr-14.
1581.2Sgarbled	 * We have to rewrite the interrupt map, because the bridge map told
1591.2Sgarbled	 * us that the interrupt is MPIC 0, which is the bridge intr for
1601.2Sgarbled	 * the 8259.
1611.2Sgarbled	 * Additionally, sometimes the PCI Interrupt Routing Control Register
1621.2Sgarbled	 * is improperly initialized, causing all sorts of wierd interrupt
1631.2Sgarbled	 * issues on the machine.  The manual says it should default to
1641.2Sgarbled	 * 0000h (index 45-44h) however it would appear that PPCBUG is
1651.2Sgarbled	 * setting it up differently.  Reset it to 0000h.
1661.2Sgarbled	 */
1671.2Sgarbled
1681.3Sgarbled	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SYMPHONY &&
1691.3Sgarbled	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SYMPHONY_83C553) {
1701.3Sgarbled		v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44) & 0xffff0000;
1711.3Sgarbled		pci_conf_write(pa->pa_pc, pa->pa_tag, 0x44, v);
1721.3Sgarbled	}
1731.3Sgarbled
1741.2Sgarbled#ifdef prep
1751.2Sgarbled	rav = prop_dictionary_get(device_properties(parent),
1761.2Sgarbled	    "prep-raven-pchb");
1771.2Sgarbled
1781.2Sgarbled	if (rav != NULL && prop_bool_true(rav) &&
1791.2Sgarbled	    PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SYMPHONY &&
1801.2Sgarbled	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SYMPHONY_83C553) {
1811.2Sgarbled
1821.2Sgarbled		prop_dictionary_t dict, devsub;
1831.2Sgarbled		prop_number_t pinsub;
1841.2Sgarbled		struct genppc_pci_chipset_businfo *pbi;
1851.2Sgarbled
1861.2Sgarbled		v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40) & 0x00ffffff;
1871.2Sgarbled		v |= 0xee000000;
1881.2Sgarbled		pci_conf_write(pa->pa_pc, pa->pa_tag, 0x40, v);
1891.2Sgarbled
1901.2Sgarbled		pbi = SIMPLEQ_FIRST(&genppc_pct->pc_pbi);
1911.2Sgarbled		dict = prop_dictionary_get(pbi->pbi_properties,
1921.2Sgarbled		    "prep-pci-intrmap");
1931.2Sgarbled		devsub = prop_dictionary_get(dict, "devfunc-11");
1941.2Sgarbled		pinsub = prop_number_create_integer(14);
1951.2Sgarbled		prop_dictionary_set(devsub, "pin-A", pinsub);
1961.2Sgarbled		prop_object_release(pinsub);
1971.4Smatt		aprint_verbose_dev(self, "setting pciide irq to 14\n");
1981.2Sgarbled		/* irq 14 is level */
1991.2Sgarbled		lvlmask = 0x0040;
2001.2Sgarbled	}
2011.2Sgarbled#endif /* prep */
2021.2Sgarbled
2031.2Sgarbled	config_defer(self, pcib_callback);
2041.2Sgarbled}
2051.2Sgarbled
2061.2Sgarbledvoid
2071.4Smattpcib_callback(device_t self)
2081.2Sgarbled{
2091.4Smatt	struct pcib_softc *sc = device_private(self);
2101.2Sgarbled#if NISA > 0
2111.2Sgarbled	struct isabus_attach_args iba;
2121.2Sgarbled
2131.2Sgarbled	/*
2141.2Sgarbled	 * Attach the ISA bus behind this bridge.
2151.2Sgarbled	 */
2161.2Sgarbled	memset(&iba, 0, sizeof(iba));
2171.2Sgarbled	sc->sc_chipset = &genppc_ict;
2181.2Sgarbled	iba.iba_ic = sc->sc_chipset;
2191.2Sgarbled	iba.iba_iot = &genppc_isa_io_space_tag;
2201.2Sgarbled	iba.iba_memt = &genppc_isa_mem_space_tag;
2211.2Sgarbled#if NISADMA > 0
2221.2Sgarbled	iba.iba_dmat = &isa_bus_dma_tag;
2231.2Sgarbled#endif
2241.4Smatt	config_found_ia(sc->sc_dev, "isabus", &iba, isabusprint);
2251.2Sgarbled#endif
2261.2Sgarbled}
227