ofw_pci.c revision 107472
150724Scg/*
250724Scg * Copyright (c) 1999, 2000 Matthew R. Green
350724Scg * All rights reserved.
450724Scg * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>.  All rights reserved.
550724Scg *
650724Scg * Redistribution and use in source and binary forms, with or without
750724Scg * modification, are permitted provided that the following conditions
850724Scg * are met:
950724Scg * 1. Redistributions of source code must retain the above copyright
1050724Scg *    notice, this list of conditions and the following disclaimer.
1150724Scg * 2. Redistributions in binary form must reproduce the above copyright
1250724Scg *    notice, this list of conditions and the following disclaimer in the
1350724Scg *    documentation and/or other materials provided with the distribution.
1450724Scg * 3. The name of the author may not be used to endorse or promote products
1550724Scg *    derived from this software without specific prior written permission.
1650724Scg *
1750724Scg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1850724Scg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1950724Scg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2050724Scg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2150724Scg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2250724Scg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2350724Scg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2450724Scg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2550724Scg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2650733Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2750724Scg * SUCH DAMAGE.
2850724Scg *
2950724Scg *	from: NetBSD: psycho.c,v 1.35 2001/09/10 16:17:06 eeh Exp
3050724Scg *
3150724Scg * $FreeBSD: head/sys/sparc64/pci/ofw_pci.c 107472 2002-12-01 23:06:14Z tmm $
3250724Scg */
3350724Scg
3450724Scg#include "opt_ofw_pci.h"
3550724Scg
3650724Scg#include <sys/param.h>
3750724Scg#include <sys/kernel.h>
3850724Scg#include <sys/systm.h>
3950724Scg#include <sys/bus.h>
4050724Scg
4150724Scg#include <dev/pci/pcivar.h>
4250724Scg#include <dev/pci/pcireg.h>
4350724Scg
4450724Scg#include <dev/ofw/ofw_pci.h>
4550724Scg#include <dev/ofw/openfirm.h>
4650724Scg
4750724Scg#include <sparc64/pci/ofw_pci.h>
4850724Scg
4950724Scg#include <machine/ofw_bus.h>
5050724Scg#include <machine/ver.h>
5150724Scg
5250724Scg#include "pcib_if.h"
5350724Scg
5450724Scgu_int8_t pci_bus_cnt;
5550724Scgphandle_t *pci_bus_map;
5650724Scgint pci_bus_map_sz;
5750724Scg
5850724Scg#define	OPQ_NO_SWIZZLE	1
5950724Scgstatic struct ofw_pci_quirk {
6050724Scg	char	*opq_model;
6150724Scg	int	opq_quirks;
6250724Scg} ofw_pci_quirks[] = {
6350724Scg	{ "SUNW,Ultra-4", OPQ_NO_SWIZZLE },
6450724Scg	{ "SUNW,Ultra-1-Engine", OPQ_NO_SWIZZLE },
6550724Scg};
6650724Scg#define	OPQ_NENT	(sizeof(ofw_pci_quirks) / sizeof(ofw_pci_quirks[0]))
6750724Scg
6850724Scgstatic int pci_quirks;
6950724Scg
7050724Scg#define	OFW_PCI_PCIBUS	"pci"
7150724Scg#define	PCI_BUS_MAP_INC	10
7250724Scg
7350724Scgint
7450724Scgofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
7550724Scg    u_int8_t *pregptr, int pregsz, u_int8_t **rintr, int *terminate)
7650724Scg{
7750724Scg	struct ofw_pci_register preg;
7850724Scg	u_int32_t pintr, intr;
7950724Scg	char type[32];
8050724Scg
8150724Scg	if (pintsz != sizeof(u_int32_t))
8250724Scg		return (-1);
8350724Scg	bcopy(pintptr, &pintr, sizeof(pintr));
8450724Scg	if ((pci_quirks & OPQ_NO_SWIZZLE) == 0 && pregsz >= sizeof(preg) &&
8550724Scg	    OF_getprop(node, "device_type", type, sizeof(type)) != -1 &&
8650724Scg	    strcmp(type, OFW_PCI_PCIBUS) == 0 && pintr >= 1 && pintr <= 4) {
8750724Scg		/*
8850724Scg		 * Handle a quirk found on some Netra t1 models: there exist
8950724Scg		 * PCI bridges without interrupt maps, where we apparently must
9050724Scg		 * do the PCI swizzle and continue to map on at the parent.
9150724Scg		 */
9250724Scg		bcopy(pregptr, &preg, sizeof(preg));
9350724Scg		intr = (OFW_PCI_PHYS_HI_DEVICE(preg.phys_hi) + pintr + 3) %
9450724Scg		    4 + 1;
9550724Scg		*rintr = malloc(sizeof(intr), M_OFWPROP, M_WAITOK);
9650724Scg		bcopy(&intr, *rintr, sizeof(intr));
9750724Scg		*terminate = 0;
9850724Scg		return (sizeof(intr));
9950724Scg	}
10050724Scg	return (-1);
10150724Scg}
10250724Scg
10350724Scgu_int32_t
10450724Scgofw_pci_route_intr(phandle_t node, u_int32_t ign)
10550724Scg{
10650724Scg	u_int32_t rv;
10750724Scg
10850724Scg	rv = ofw_bus_route_intr(node, ORIP_NOINT, ofw_pci_orb_callback);
10953205Scg	if (rv == ORIR_NOTFOUND)
11050724Scg		return (255);
11150923Scg	/*
11250724Scg	 * Some machines (notably the SPARCengine Ultra AX) have no mappings
11353205Scg	 * at all, but use complete interrupt vector number including the IGN.
11453205Scg	 * Catch this case and remove the IGN.
11553205Scg	 */
11653205Scg	if (rv > ign)
11753205Scg		rv -= ign;
11853205Scg	return (rv);
11953205Scg}
12050923Scg
12150923Scgu_int8_t
12250923Scgofw_pci_alloc_busno(phandle_t node)
12350923Scg{
12450923Scg	phandle_t *om;
12550923Scg	int osz;
12650923Scg	u_int8_t n;
12752713Stanimura
12852713Stanimura	n = pci_bus_cnt++;
12950724Scg	/* Establish a mapping between bus numbers and device nodes. */
13051769Scg	if (n >= pci_bus_map_sz) {
13150724Scg		osz = pci_bus_map_sz;
13250724Scg		om = pci_bus_map;
13350724Scg		pci_bus_map_sz = n + PCI_BUS_MAP_INC;
13450724Scg		pci_bus_map = malloc(sizeof(*pci_bus_map) * pci_bus_map_sz,
13553205Scg		    M_DEVBUF, M_WAITOK | M_ZERO);
13650724Scg		if (om != NULL) {
13750724Scg			bcopy(om, pci_bus_map, sizeof(*om) * osz);
13853205Scg			free(om, M_DEVBUF);
13950724Scg		}
14050724Scg	}
14150724Scg	pci_bus_map[n] = node;
14250724Scg	return (n);
14350724Scg}
14450724Scg
14550724Scg/*
14650724Scg * Initialize bridge bus numbers for bridges that implement the primary,
14751769Scg * secondary and subordinate bus number registers.
14850724Scg */
14950724Scgvoid
15050724Scgofw_pci_binit(device_t busdev, struct ofw_pci_bdesc *obd)
15150724Scg{
15250724Scg
15350724Scg#ifdef OFW_PCI_DEBUG
15450724Scg	printf("PCI-PCI bridge at %u/%u/%u: setting bus #s to %u/%u/%u\n",
15550724Scg	    obd->obd_bus, obd->obd_slot, obd->obd_func, obd->obd_bus,
15650724Scg	    obd->obd_secbus, obd->obd_subbus);
15750724Scg#endif /* OFW_PCI_DEBUG */
15850724Scg	PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
15950724Scg	    PCIR_PRIBUS_1, obd->obd_bus, 1);
16050724Scg	PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
16150724Scg	    PCIR_SECBUS_1, obd->obd_secbus, 1);
16250724Scg	PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
16350724Scg	    PCIR_SUBBUS_1, obd->obd_subbus, 1);
16450724Scg}
16550724Scg
16650724Scg/*
16753205Scg * Walk the PCI bus hierarchy, starting with the root PCI bus and descending
16850724Scg * through bridges, and initialize the interrupt line and latency timer
16950724Scg * configuration registers of attached devices using firmware information,
17050724Scg * as well as the the bus numbers and ranges of the bridges.
17153205Scg */
17250724Scgvoid
17350724Scgofw_pci_init(device_t dev, phandle_t bushdl, u_int32_t ign,
17450724Scg    struct ofw_pci_bdesc *obd)
17550724Scg{
17650724Scg	struct ofw_pci_register pcir;
17750724Scg	struct ofw_pci_bdesc subobd, *tobd;
17850724Scg	phandle_t node;
17951769Scg	char type[32];
18050724Scg	int i, intr, freemap;
18150724Scg	u_int slot, busno, func, sub, lat;
18250724Scg
18350724Scg	/* Initialize the quirk list. */
18453205Scg	for (i = 0; i < OPQ_NENT; i++) {
18550724Scg		if (strcmp(sparc64_model, ofw_pci_quirks[i].opq_model) == 0) {
18653205Scg			pci_quirks = ofw_pci_quirks[i].opq_quirks;
18750724Scg			break;
18850724Scg		}
18950724Scg	}
19050724Scg
19150724Scg	if ((node = OF_child(bushdl)) == 0)
19250724Scg		return;
19350724Scg	freemap = 0;
19450724Scg	busno = obd->obd_secbus;
19550724Scg	do {
19650724Scg		if (node == -1)
19751769Scg			panic("ofw_pci_init_intr: OF_child failed");
19850724Scg		if (OF_getprop(node, "device_type", type, sizeof(type)) == -1)
19950724Scg			type[0] = '\0';
20050724Scg		else
20150724Scg			type[sizeof(type) - 1] = '\0';
20250724Scg		if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
20350724Scg			panic("ofw_pci_init: OF_getprop failed");
20450724Scg		slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
20550724Scg		func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
20650724Scg		if (strcmp(type, OFW_PCI_PCIBUS) == 0) {
20750724Scg			/*
20850724Scg			 * This is a pci-pci bridge, initalize the bus number and
20950724Scg			 * recurse to initialize the child bus. The hierarchy is
21050724Scg			 * usually at most 2 levels deep, so recursion is
21150724Scg			 * feasible.
21250724Scg			 */
21350724Scg			subobd.obd_bus = busno;
21450724Scg			subobd.obd_slot = slot;
21550724Scg			subobd.obd_func = func;
21650724Scg			sub = ofw_pci_alloc_busno(node);
21753205Scg			subobd.obd_secbus = subobd.obd_subbus = sub;
21850724Scg			/* Assume this bridge is mostly standard conforming. */
21950724Scg			subobd.obd_init = ofw_pci_binit;
22050724Scg			subobd.obd_super = obd;
22153205Scg			/*
22250724Scg			 * Need to change all subordinate bus registers of the
22350724Scg			 * bridges above this one now so that configuration
22450724Scg			 * transactions will get through.
22550724Scg			 */
22650724Scg			for (tobd = obd; tobd != NULL; tobd = tobd->obd_super) {
22750724Scg				tobd->obd_subbus = sub;
22850724Scg				tobd->obd_init(dev, tobd);
22951769Scg			}
23050724Scg			subobd.obd_init(dev, &subobd);
23150724Scg#ifdef OFW_PCI_DEBUG
23250724Scg			device_printf(dev, "%s: descending to "
23350724Scg			    "subordinate PCI bus\n", __func__);
23450724Scg#endif /* OFW_PCI_DEBUG */
23553205Scg			ofw_pci_init(dev, node, ign, &subobd);
23650724Scg		} else {
23750724Scg			/*
23853205Scg			 * Initialize the latency timer register for
23950724Scg			 * busmaster devices to work properly. This is another
24050724Scg			 * task which the firmware does not always perform.
24150724Scg			 * The Min_Gnt register can be used to compute it's
24250724Scg			 * recommended value: it contains the desired latency
24350724Scg			 * in units of 1/4 us. To calculate the correct latency
24450724Scg			 * timer value, a bus clock of 33 and no wait states
24550923Scg			 * should be assumed.
24650724Scg			 */
24751769Scg			lat = PCIB_READ_CONFIG(dev, busno, slot, func,
24850724Scg			    PCIR_MINGNT, 1) * 33 / 4;
24950724Scg			if (lat != 0) {
25050724Scg#ifdef OFW_PCI_DEBUG
25150724Scg				printf("device %d/%d/%d: latency timer %d -> "
25253205Scg				    "%d\n", busno, slot, func,
25350724Scg				    PCIB_READ_CONFIG(dev, busno, slot, func,
25453205Scg					PCIR_LATTIMER, 1), lat);
25550724Scg#endif /* OFW_PCI_DEBUG */
25650724Scg				PCIB_WRITE_CONFIG(dev, busno, slot, func,
25750724Scg				    PCIR_LATTIMER, imin(lat, 255), 1);
25850724Scg			}
25950724Scg
26050724Scg			/* Initialize the intline registers. */
26150724Scg			if ((intr = ofw_pci_route_intr(node, ign)) != 255) {
26250724Scg#ifdef OFW_PCI_DEBUG
26351769Scg				device_printf(dev, "%s: mapping intr for "
26450724Scg				    "%d/%d/%d to %d (preset was %d)\n",
26551769Scg				    __func__, busno, slot, func, intr,
26650724Scg				    (int)PCIB_READ_CONFIG(dev, busno, slot,
26750724Scg					func, PCIR_INTLINE, 1));
26850724Scg#endif /* OFW_PCI_DEBUG */
26950724Scg				PCIB_WRITE_CONFIG(dev, busno, slot, func,
27053205Scg				    PCIR_INTLINE, intr, 1);
27150724Scg			} else {
27253205Scg#ifdef OFW_PCI_DEBUG
27350724Scg				device_printf(dev, "%s: no interrupt "
27450724Scg				    "mapping found for %d/%d/%d (preset %d)\n",
27550724Scg				    __func__, busno, slot, func,
27650724Scg				    (int)PCIB_READ_CONFIG(dev, busno, slot,
27750724Scg					func, PCIR_INTLINE, 1));
27850724Scg#endif /* OFW_PCI_DEBUG */
27950724Scg				/*
28051769Scg				 * The firmware initializes to 0 instead of
28150724Scg				 * 255.
28251769Scg				 */
28350724Scg				PCIB_WRITE_CONFIG(dev, busno, slot, func,
28450724Scg				    PCIR_INTLINE, 255, 1);
28550724Scg			}
28650724Scg		}
28750724Scg	} while ((node = OF_peer(node)) != 0);
28850724Scg}
28950724Scg
29050724Scgphandle_t
29150724Scgofw_pci_find_node(int bus, int slot, int func)
29250724Scg{
29350724Scg	phandle_t node, bnode;
29450724Scg	struct ofw_pci_register pcir;
29550724Scg
29650724Scg	/*
29750724Scg	 * Retrieve the bus node from the mapping that was created on
29850724Scg	 * initialization. The bus numbers the firmware uses cannot be trusted,
29950724Scg	 * so they might have needed to be changed and this is necessary.
30050724Scg	 */
30150724Scg	if (bus >= pci_bus_map_sz)
30250724Scg		return (0);
30350724Scg	bnode = pci_bus_map[bus];
30450724Scg	if (bnode == 0)
30550724Scg		return (0);
30650724Scg	for (node = OF_child(bnode); node != 0 && node != -1;
30750724Scg	     node = OF_peer(node)) {
30850724Scg		if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
30950724Scg			continue;
31050724Scg		if (OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi) == slot &&
31150724Scg		    OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi) == func)
31250724Scg			return (node);
31350724Scg	}
31450724Scg	return (0);
31550724Scg}
31650724Scg
31750724Scgphandle_t
31850724Scgofw_pci_node(device_t dev)
31950724Scg{
32050724Scg
32150724Scg	return (ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev),
32250724Scg	    pci_get_function(dev)));
32350724Scg}
32450724Scg