pcib.c revision 1.2
11.2Sgarbled/*	$NetBSD: pcib.c,v 1.2 2007/10/17 19:56:44 garbled 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.2Sgarbled__KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.2 2007/10/17 19:56:44 garbled 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.2Sgarbledint	pcibmatch(struct device *, struct cfdata *, void *);
601.2Sgarbledvoid	pcibattach(struct device *, struct device *, void *);
611.2Sgarbled
621.2Sgarbledstruct pcib_softc {
631.2Sgarbled	struct device 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.2SgarbledCFATTACH_DECL(pcib, sizeof(struct pcib_softc),
711.2Sgarbled    pcibmatch, pcibattach, NULL, NULL);
721.2Sgarbled
731.2Sgarbledvoid	pcib_callback(struct device *);
741.2Sgarbled
751.2Sgarbledint
761.2Sgarbledpcibmatch(struct device *parent, struct cfdata *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.2Sgarbledpcibattach(struct device *parent, struct device *self, void *aux)
1091.2Sgarbled{
1101.2Sgarbled	struct pci_attach_args *pa = aux;
1111.2Sgarbled	char devinfo[256];
1121.2Sgarbled	u_int32_t v;
1131.2Sgarbled	int lvlmask = 0;
1141.2Sgarbled#ifdef prep
1151.2Sgarbled	prop_bool_t rav;
1161.2Sgarbled#endif
1171.2Sgarbled
1181.2Sgarbled	/*
1191.2Sgarbled	 * Just print out a description and defer configuration
1201.2Sgarbled	 * until all PCI devices have been attached.
1211.2Sgarbled	 */
1221.2Sgarbled	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
1231.2Sgarbled	aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
1241.2Sgarbled	    PCI_REVISION(pa->pa_class));
1251.2Sgarbled
1261.2Sgarbled	v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40);
1271.2Sgarbled	if ((v & 0x20) == 0) {
1281.2Sgarbled		aprint_verbose("%s: PIRQ[0-3] not used\n", self->dv_xname);
1291.2Sgarbled	} else {
1301.2Sgarbled		v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x60);
1311.2Sgarbled		if ((v & 0x80808080) == 0x80808080) {
1321.2Sgarbled			aprint_verbose("%s: PIRQ[0-3] disabled\n",
1331.2Sgarbled			    self->dv_xname);
1341.2Sgarbled		} else {
1351.2Sgarbled			int i;
1361.2Sgarbled			aprint_verbose("%s:", self->dv_xname);
1371.2Sgarbled			for (i = 0; i < 4; i++, v >>= 8) {
1381.2Sgarbled				if ((v & 0x80) == 0 && (v & 0x0f) != 0) {
1391.2Sgarbled					aprint_verbose(" PIRQ[%d]=%d", i,
1401.2Sgarbled					    v & 0x0f);
1411.2Sgarbled					lvlmask |= (1 << (v & 0x0f));
1421.2Sgarbled				}
1431.2Sgarbled			}
1441.2Sgarbled			aprint_verbose("\n");
1451.2Sgarbled		}
1461.2Sgarbled	}
1471.2Sgarbled
1481.2Sgarbled	/*
1491.2Sgarbled	 * If we have an 83C553F-G sitting on a RAVEN host bridge,
1501.2Sgarbled	 * then we need to rewire some interrupts.
1511.2Sgarbled	 * The IDE Interrupt Routing Control Register lives at 0x43,
1521.2Sgarbled	 * and defaults to 0xEF, which means the primary controller
1531.2Sgarbled	 * interrupts on ivr-14, and the secondary on ivr-15. We
1541.2Sgarbled	 * reset it to 0xEE to fire them both at ivr-14.
1551.2Sgarbled	 * We have to rewrite the interrupt map, because the bridge map told
1561.2Sgarbled	 * us that the interrupt is MPIC 0, which is the bridge intr for
1571.2Sgarbled	 * the 8259.
1581.2Sgarbled	 * Additionally, sometimes the PCI Interrupt Routing Control Register
1591.2Sgarbled	 * is improperly initialized, causing all sorts of wierd interrupt
1601.2Sgarbled	 * issues on the machine.  The manual says it should default to
1611.2Sgarbled	 * 0000h (index 45-44h) however it would appear that PPCBUG is
1621.2Sgarbled	 * setting it up differently.  Reset it to 0000h.
1631.2Sgarbled	 */
1641.2Sgarbled
1651.2Sgarbled#ifdef prep
1661.2Sgarbled	rav = prop_dictionary_get(device_properties(parent),
1671.2Sgarbled	    "prep-raven-pchb");
1681.2Sgarbled
1691.2Sgarbled	if (rav != NULL && prop_bool_true(rav) &&
1701.2Sgarbled	    PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SYMPHONY &&
1711.2Sgarbled	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SYMPHONY_83C553) {
1721.2Sgarbled
1731.2Sgarbled		prop_dictionary_t dict, devsub;
1741.2Sgarbled		prop_number_t pinsub;
1751.2Sgarbled		struct genppc_pci_chipset_businfo *pbi;
1761.2Sgarbled
1771.2Sgarbled		v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40) & 0x00ffffff;
1781.2Sgarbled		v |= 0xee000000;
1791.2Sgarbled		pci_conf_write(pa->pa_pc, pa->pa_tag, 0x40, v);
1801.2Sgarbled
1811.2Sgarbled		v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44) & 0xffff0000;
1821.2Sgarbled		pci_conf_write(pa->pa_pc, pa->pa_tag, 0x44, v);
1831.2Sgarbled
1841.2Sgarbled		pbi = SIMPLEQ_FIRST(&genppc_pct->pc_pbi);
1851.2Sgarbled		dict = prop_dictionary_get(pbi->pbi_properties,
1861.2Sgarbled		    "prep-pci-intrmap");
1871.2Sgarbled		devsub = prop_dictionary_get(dict, "devfunc-11");
1881.2Sgarbled		pinsub = prop_number_create_integer(14);
1891.2Sgarbled		prop_dictionary_set(devsub, "pin-A", pinsub);
1901.2Sgarbled		prop_object_release(pinsub);
1911.2Sgarbled		aprint_verbose("%s: setting pciide irq to 14\n",
1921.2Sgarbled		    self->dv_xname);
1931.2Sgarbled		/* irq 14 is level */
1941.2Sgarbled		lvlmask = 0x0040;
1951.2Sgarbled	}
1961.2Sgarbled#endif /* prep */
1971.2Sgarbled
1981.2Sgarbled	config_defer(self, pcib_callback);
1991.2Sgarbled}
2001.2Sgarbled
2011.2Sgarbledvoid
2021.2Sgarbledpcib_callback(struct device *self)
2031.2Sgarbled{
2041.2Sgarbled	struct pcib_softc *sc = (struct pcib_softc *)self;
2051.2Sgarbled#if NISA > 0
2061.2Sgarbled	struct isabus_attach_args iba;
2071.2Sgarbled
2081.2Sgarbled	/*
2091.2Sgarbled	 * Attach the ISA bus behind this bridge.
2101.2Sgarbled	 */
2111.2Sgarbled	memset(&iba, 0, sizeof(iba));
2121.2Sgarbled	sc->sc_chipset = &genppc_ict;
2131.2Sgarbled	iba.iba_ic = sc->sc_chipset;
2141.2Sgarbled	iba.iba_iot = &genppc_isa_io_space_tag;
2151.2Sgarbled	iba.iba_memt = &genppc_isa_mem_space_tag;
2161.2Sgarbled#if NISADMA > 0
2171.2Sgarbled	iba.iba_dmat = &isa_bus_dma_tag;
2181.2Sgarbled#endif
2191.2Sgarbled	config_found_ia(&sc->sc_dev, "isabus", &iba, isabusprint);
2201.2Sgarbled#endif
2211.2Sgarbled}
222