xref: /netbsd-src/sys/arch/sparc64/dev/pci_machdep.c (revision e5548b402ae4c44fb816de42c7bba9581ce23ef5)
1 /*	$NetBSD: pci_machdep.c,v 1.50 2005/12/11 12:19:09 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1999, 2000 Matthew R. Green
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 /*
32  * functions expected by the MI PCI code.
33  */
34 
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.50 2005/12/11 12:19:09 christos Exp $");
37 
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/time.h>
41 #include <sys/systm.h>
42 #include <sys/errno.h>
43 #include <sys/device.h>
44 #include <sys/malloc.h>
45 
46 #define _SPARC_BUS_DMA_PRIVATE
47 #include <machine/bus.h>
48 #include <machine/autoconf.h>
49 #include <machine/openfirm.h>
50 #include <dev/pci/pcivar.h>
51 #include <dev/pci/pcireg.h>
52 
53 #include <dev/ofw/ofw_pci.h>
54 
55 #include <sparc64/dev/iommureg.h>
56 #include <sparc64/dev/iommuvar.h>
57 #include <sparc64/dev/psychoreg.h>
58 #include <sparc64/dev/psychovar.h>
59 #include <sparc64/sparc64/cache.h>
60 
61 #include "locators.h"
62 
63 #ifdef DEBUG
64 #define SPDB_CONF	0x01
65 #define SPDB_INTR	0x04
66 #define SPDB_INTMAP	0x08
67 #define SPDB_PROBE	0x20
68 int sparc_pci_debug = 0x0;
69 #define DPRINTF(l, s)	do { if (sparc_pci_debug & l) printf s; } while (0)
70 #else
71 #define DPRINTF(l, s)
72 #endif
73 
74 /* this is a base to be copied */
75 struct sparc_pci_chipset _sparc_pci_chipset = {
76 	NULL,
77 };
78 
79 static int pci_find_ino(struct pci_attach_args *, pci_intr_handle_t *);
80 
81 static pcitag_t
82 ofpci_make_tag(pci_chipset_tag_t pc, int node, int b, int d, int f)
83 {
84 	pcitag_t tag;
85 
86 	tag = PCITAG_CREATE(node, b, d, f);
87 
88 	/* Enable all the different spaces for this device */
89 	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
90 		PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE|
91 		PCI_COMMAND_IO_ENABLE);
92 	return (tag);
93 }
94 
95 /*
96  * functions provided to the MI code.
97  */
98 
99 void
100 pci_attach_hook(parent, self, pba)
101 	struct device *parent;
102 	struct device *self;
103 	struct pcibus_attach_args *pba;
104 {
105 }
106 
107 int
108 pci_bus_maxdevs(pc, busno)
109 	pci_chipset_tag_t pc;
110 	int busno;
111 {
112 
113 	return 32;
114 }
115 
116 pcitag_t
117 pci_make_tag(pc, b, d, f)
118 	pci_chipset_tag_t pc;
119 	int b;
120 	int d;
121 	int f;
122 {
123 	struct psycho_pbm *pp = pc->cookie;
124 	struct ofw_pci_register reg;
125 	pcitag_t tag;
126 	int (*valid) __P((void *));
127 	int node, len;
128 #ifdef DEBUG
129 	char name[80];
130 	memset(name, 0, sizeof(name));
131 #endif
132 
133 	/*
134 	 * Refer to the PCI/CardBus bus node first.
135 	 * It returns a tag if node is present and bus is valid.
136 	 */
137 	if (0 <= b && b < 256) {
138 		node = (*pp->pp_busnode)[b].node;
139 		valid = (*pp->pp_busnode)[b].valid;
140 		if (node != 0 && d == 0 &&
141 		    (valid == NULL || (*valid)((*pp->pp_busnode)[b].arg)))
142 			return ofpci_make_tag(pc, node, b, d, f);
143 	}
144 
145 	/*
146 	 * Hunt for the node that corresponds to this device
147 	 *
148 	 * We could cache this info in an array in the parent
149 	 * device... except then we have problems with devices
150 	 * attached below pci-pci bridges, and we would need to
151 	 * add special code to the pci-pci bridge to cache this
152 	 * info.
153 	 */
154 
155 	tag = PCITAG_CREATE(-1, b, d, f);
156 	node = pc->rootnode;
157 	/*
158 	 * First make sure we're on the right bus.  If our parent
159 	 * has a bus-range property and we're not in the range,
160 	 * then we're obviously on the wrong bus.  So go up one
161 	 * level.
162 	 */
163 #ifdef DEBUG
164 	if (sparc_pci_debug & SPDB_PROBE) {
165 		printf("curnode %x %s\n", node,
166 			prom_getpropstringA(node, "name", name, sizeof(name)));
167 	}
168 #endif
169 #if 0
170 	while ((OF_getprop(OF_parent(node), "bus-range", (void *)&busrange,
171 		sizeof(busrange)) == sizeof(busrange)) &&
172 		(b < busrange[0] || b > busrange[1])) {
173 		/* Out of range, go up one */
174 		node = OF_parent(node);
175 #ifdef DEBUG
176 		if (sparc_pci_debug & SPDB_PROBE) {
177 			printf("going up to node %x %s\n", node,
178 			prom_getpropstringA(node, "name", name, sizeof(name)));
179 		}
180 #endif
181 	}
182 #endif
183 	/*
184 	 * Now traverse all peers until we find the node or we find
185 	 * the right bridge.
186 	 *
187 	 * XXX We go up one and down one to make sure nobody's missed.
188 	 * but this should not be necessary.
189 	 */
190 	for (node = ((node)); node; node = prom_nextsibling(node)) {
191 
192 #ifdef DEBUG
193 		if (sparc_pci_debug & SPDB_PROBE) {
194 			printf("checking node %x %s\n", node,
195 			prom_getpropstringA(node, "name", name, sizeof(name)));
196 
197 		}
198 #endif
199 
200 #if 1
201 		/*
202 		 * Check for PCI-PCI bridges.  If the device we want is
203 		 * in the bus-range for that bridge, work our way down.
204 		 */
205 		while (1) {
206 			int busrange[2], *brp;
207 			len = 2;
208 			brp = busrange;
209 			if (prom_getprop(node, "bus-range", sizeof(*brp),
210 					 &len, &brp) != 0)
211 				break;
212 			if (len != 2 || b < busrange[0] || b > busrange[1])
213 				break;
214 			/* Go down 1 level */
215 			node = prom_firstchild(node);
216 #ifdef DEBUG
217 			if (sparc_pci_debug & SPDB_PROBE) {
218 				printf("going down to node %x %s\n", node,
219 					prom_getpropstringA(node, "name",
220 							name, sizeof(name)));
221 			}
222 #endif
223 		}
224 #endif /*1*/
225 		/*
226 		 * We only really need the first `reg' property.
227 		 *
228 		 * For simplicity, we'll query the `reg' when we
229 		 * need it.  Otherwise we could malloc() it, but
230 		 * that gets more complicated.
231 		 */
232 		len = prom_getproplen(node, "reg");
233 		if (len < sizeof(reg))
234 			continue;
235 		if (OF_getprop(node, "reg", (void *)&reg, sizeof(reg)) != len)
236 			panic("pci_probe_bus: OF_getprop len botch");
237 
238 		if (b != OFW_PCI_PHYS_HI_BUS(reg.phys_hi))
239 			continue;
240 		if (d != OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi))
241 			continue;
242 		if (f != OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi))
243 			continue;
244 
245 		/* Got a match */
246 		tag = ofpci_make_tag(pc, node, b, d, f);
247 
248 		return (tag);
249 	}
250 	/* No device found -- return a dead tag */
251 	return (tag);
252 }
253 
254 void
255 pci_decompose_tag(pc, tag, bp, dp, fp)
256 	pci_chipset_tag_t pc;
257 	pcitag_t tag;
258 	int *bp, *dp, *fp;
259 {
260 
261 	if (bp != NULL)
262 		*bp = PCITAG_BUS(tag);
263 	if (dp != NULL)
264 		*dp = PCITAG_DEV(tag);
265 	if (fp != NULL)
266 		*fp = PCITAG_FUN(tag);
267 }
268 
269 int
270 sparc64_pci_enumerate_bus(struct pci_softc *sc, const int *locators,
271     int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
272 {
273 	struct ofw_pci_register reg;
274 	pci_chipset_tag_t pc = sc->sc_pc;
275 	pcitag_t tag;
276 	pcireg_t class, csr, bhlc, ic;
277 	int node, b, d, f, ret;
278 	int bus_frequency, lt, cl, cacheline;
279 	char name[30];
280 	extern int pci_config_dump;
281 
282 	if (sc->sc_bridgetag)
283 		node = PCITAG_NODE(*sc->sc_bridgetag);
284 	else
285 		node = pc->rootnode;
286 
287 	bus_frequency =
288 		prom_getpropint(node, "clock-frequency", 33000000) / 1000000;
289 
290 	/*
291 	 * Make sure the cache line size is at least as big as the
292 	 * ecache line and the streaming cache (64 byte).
293 	 */
294 	cacheline = max(cacheinfo.ec_linesize, 64);
295 	KASSERT((cacheline/64)*64 == cacheline &&
296 	    (cacheline/cacheinfo.ec_linesize)*cacheinfo.ec_linesize == cacheline &&
297 	    (cacheline/4)*4 == cacheline);
298 
299 	/* Turn on parity for the bus. */
300 	tag = ofpci_make_tag(pc, node, sc->sc_bus, 0, 0);
301 	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
302 	csr |= PCI_COMMAND_PARITY_ENABLE;
303 	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
304 
305 	/*
306 	 * Initialize the latency timer register.
307 	 * The value 0x40 is from Solaris.
308 	 */
309 	bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG);
310 	bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
311 	bhlc |= 0x40 << PCI_LATTIMER_SHIFT;
312 	pci_conf_write(pc, tag, PCI_BHLC_REG, bhlc);
313 
314 	if (pci_config_dump) pci_conf_print(pc, tag, NULL);
315 
316 	for (node = prom_firstchild(node); node != 0 && node != -1;
317 	     node = prom_nextsibling(node)) {
318 		name[0] = name[29] = 0;
319 		prom_getpropstringA(node, "name", name, sizeof(name));
320 
321 		if (OF_getprop(node, "class-code", &class, sizeof(class)) !=
322 		    sizeof(class))
323 			continue;
324 		if (OF_getprop(node, "reg", &reg, sizeof(reg)) < sizeof(reg))
325 			panic("pci_enumerate_bus: \"%s\" regs too small", name);
326 
327 		b = OFW_PCI_PHYS_HI_BUS(reg.phys_hi);
328 		d = OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi);
329 		f = OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi);
330 
331 		if (sc->sc_bus != b) {
332 			printf("%s: WARNING: incorrect bus # for \"%s\" "
333 			"(%d/%d/%d)\n", sc->sc_dev.dv_xname, name, b, d, f);
334 			continue;
335 		}
336                 if ((locators[PCICF_DEV] != PCICF_DEV_DEFAULT) &&
337                     (locators[PCICF_DEV] != d))
338                         continue;
339 		if ((locators[PCICF_FUNCTION] != PCICF_FUNCTION_DEFAULT) &&
340 		    (locators[PCICF_FUNCTION] != f))
341 			continue;
342 
343 		tag = ofpci_make_tag(pc, node, b, d, f);
344 
345 		/*
346 		 * Turn on parity and fast-back-to-back for the device.
347 		 */
348 		csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
349 		if (csr & PCI_STATUS_BACKTOBACK_SUPPORT)
350 			csr |= PCI_COMMAND_BACKTOBACK_ENABLE;
351 		csr |= PCI_COMMAND_PARITY_ENABLE;
352 		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
353 
354 		/*
355 		 * Initialize the latency timer register for busmaster
356 		 * devices to work properly.
357 		 *   latency-timer = min-grant * bus-freq / 4  (from FreeBSD)
358 		 * Also initialize the cache line size register.
359 		 * Solaris anytime sets this register to the value 0x10.
360 		 */
361 		bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG);
362 		ic = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
363 
364 		lt = min(PCI_MIN_GNT(ic) * bus_frequency / 4, 255);
365 		if (lt == 0 || lt < PCI_LATTIMER(bhlc))
366 			lt = PCI_LATTIMER(bhlc);
367 
368 		cl = PCI_CACHELINE(bhlc);
369 		if (cl == 0)
370 			cl = cacheline;
371 
372 		bhlc &= ~((PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT) |
373 			  (PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT));
374 		bhlc |= (lt << PCI_LATTIMER_SHIFT) |
375 			(cl << PCI_CACHELINE_SHIFT);
376 		pci_conf_write(pc, tag, PCI_BHLC_REG, bhlc);
377 
378 		ret = pci_probe_device(sc, tag, match, pap);
379 		if (match != NULL && ret != 0)
380 			return (ret);
381 	}
382 	return (0);
383 }
384 
385 /* assume we are mapped little-endian/side-effect */
386 pcireg_t
387 pci_conf_read(pc, tag, reg)
388 	pci_chipset_tag_t pc;
389 	pcitag_t tag;
390 	int reg;
391 {
392 	struct psycho_pbm *pp = pc->cookie;
393 	struct psycho_softc *sc = pp->pp_sc;
394 	pcireg_t val = (pcireg_t)~0;
395 
396 	DPRINTF(SPDB_CONF, ("pci_conf_read: tag %lx reg %x ",
397 		(long)tag, reg));
398 	if (PCITAG_NODE(tag) != -1) {
399 		DPRINTF(SPDB_CONF, ("asi=%x addr=%qx (offset=%x) ...",
400 			sc->sc_configaddr._asi,
401 			(long long)(sc->sc_configaddr._ptr +
402 				PCITAG_OFFSET(tag) + reg),
403 			(int)PCITAG_OFFSET(tag) + reg));
404 
405 		val = bus_space_read_4(sc->sc_configtag, sc->sc_configaddr,
406 			PCITAG_OFFSET(tag) + reg);
407 	}
408 #ifdef DEBUG
409 	else DPRINTF(SPDB_CONF, ("pci_conf_read: bogus pcitag %x\n",
410 		(int)PCITAG_OFFSET(tag)));
411 #endif
412 	DPRINTF(SPDB_CONF, (" returning %08x\n", (u_int)val));
413 
414 	return (val);
415 }
416 
417 void
418 pci_conf_write(pc, tag, reg, data)
419 	pci_chipset_tag_t pc;
420 	pcitag_t tag;
421 	int reg;
422 	pcireg_t data;
423 {
424 	struct psycho_pbm *pp = pc->cookie;
425 	struct psycho_softc *sc = pp->pp_sc;
426 
427 	DPRINTF(SPDB_CONF, ("pci_conf_write: tag %lx; reg %x; data %x; ",
428 		(long)PCITAG_OFFSET(tag), reg, (int)data));
429 	DPRINTF(SPDB_CONF, ("asi = %x; readaddr = %qx (offset = %x)\n",
430 		sc->sc_configaddr._asi,
431 		(long long)(sc->sc_configaddr._ptr + PCITAG_OFFSET(tag) + reg),
432 		(int)PCITAG_OFFSET(tag) + reg));
433 
434 	/* If we don't know it, just punt it.  */
435 	if (PCITAG_NODE(tag) == -1) {
436 		DPRINTF(SPDB_CONF, ("pci_conf_write: bad addr"));
437 		return;
438 	}
439 
440 	bus_space_write_4(sc->sc_configtag, sc->sc_configaddr,
441 		PCITAG_OFFSET(tag) + reg, data);
442 }
443 
444 static int
445 pci_find_ino(pa, ihp)
446 	struct pci_attach_args *pa;
447 	pci_intr_handle_t *ihp;
448 {
449 	struct psycho_pbm *pp = pa->pa_pc->cookie;
450 	struct psycho_softc *sc = pp->pp_sc;
451 	u_int dev;
452 	u_int ino;
453 
454 	DPRINTF(SPDB_INTMAP, ("pci_find_ino: pa_tag: node %x, %d:%d:%d\n",
455 			      PCITAG_NODE(pa->pa_tag), (int)PCITAG_BUS(pa->pa_tag),
456 			      (int)PCITAG_DEV(pa->pa_tag),
457 			      (int)PCITAG_FUN(pa->pa_tag)));
458 	DPRINTF(SPDB_INTMAP,
459 		("pci_find_ino: intrswiz %d, intrpin %d, intrline %d, rawintrpin %d\n",
460 		 pa->pa_intrswiz, pa->pa_intrpin, pa->pa_intrline, pa->pa_rawintrpin));
461 	DPRINTF(SPDB_INTMAP, ("pci_find_ino: pa_intrtag: node %x, %d:%d:%d\n",
462 			      PCITAG_NODE(pa->pa_intrtag),
463 			      (int)PCITAG_BUS(pa->pa_intrtag),
464 			      (int)PCITAG_DEV(pa->pa_intrtag),
465 			      (int)PCITAG_FUN(pa->pa_intrtag)));
466 
467 	ino = *ihp;
468 
469 	if ((ino & ~INTMAP_PCIINT) == 0) {
470 
471 		if (pa->pa_intrswiz != 0 && PCITAG_NODE(pa->pa_intrtag) != 0)
472 			dev = PCITAG_DEV(pa->pa_intrtag);
473 		else
474 			dev = pa->pa_device;
475 
476 		if (sc->sc_mode == PSYCHO_MODE_PSYCHO &&
477 		    pp->pp_id == PSYCHO_PBM_B)
478 			dev -= 2;
479 		else
480 			dev--;
481 
482 		DPRINTF(SPDB_INTMAP, ("pci_find_ino: mode %d, pbm %d, dev %d, ino %d\n",
483 		       sc->sc_mode, pp->pp_id, dev, ino));
484 
485 		ino = (pa->pa_intrpin - 1) & INTMAP_PCIINT;
486 
487 		ino |= sc->sc_ign;
488 		ino |= ((pp->pp_id == PSYCHO_PBM_B) ? INTMAP_PCIBUS : 0);
489 		ino |= (dev << 2) & INTMAP_PCISLOT;
490 
491 		*ihp = ino;
492 	}
493 
494 	return (0);
495 }
496 
497 /*
498  * interrupt mapping foo.
499  * XXX: how does this deal with multiple interrupts for a device?
500  */
501 int
502 pci_intr_map(pa, ihp)
503 	struct pci_attach_args *pa;
504 	pci_intr_handle_t *ihp;
505 {
506 	pcitag_t tag = pa->pa_tag;
507 	int interrupts, *intp;
508 	int len, node = PCITAG_NODE(tag);
509 	char devtype[30];
510 
511 	intp = &interrupts;
512 	len = 1;
513 	if (prom_getprop(node, "interrupts", sizeof(interrupts),
514 			&len, &intp) != 0 || len != 1) {
515 		DPRINTF(SPDB_INTMAP,
516 			("pci_intr_map: could not read interrupts\n"));
517 		return (ENODEV);
518 	}
519 
520 	if (OF_mapintr(node, &interrupts, sizeof(interrupts),
521 		sizeof(interrupts)) < 0) {
522 		printf("OF_mapintr failed\n");
523 		pci_find_ino(pa, &interrupts);
524 	}
525 
526 	/* Try to find an IPL for this type of device. */
527 	prom_getpropstringA(node, "device_type", devtype, sizeof(devtype));
528 	for (len = 0; intrmap[len].in_class != NULL; len++)
529 		if (strcmp(intrmap[len].in_class, devtype) == 0) {
530 			interrupts |= INTLEVENCODE(intrmap[len].in_lev);
531 			break;
532 		}
533 
534 	/* XXXX -- we use the ino.  What if there is a valid IGN? */
535 	*ihp = interrupts;
536 	return (0);
537 }
538 
539 const char *
540 pci_intr_string(pc, ih)
541 	pci_chipset_tag_t pc;
542 	pci_intr_handle_t ih;
543 {
544 	static char str[16];
545 
546 	DPRINTF(SPDB_INTR, ("pci_intr_string: ih %u", ih));
547 	sprintf(str, "ivec %x", ih);
548 	DPRINTF(SPDB_INTR, ("; returning %s\n", str));
549 
550 	return (str);
551 }
552 
553 const struct evcnt *
554 pci_intr_evcnt(pc, ih)
555 	pci_chipset_tag_t pc;
556 	pci_intr_handle_t ih;
557 {
558 
559 	/* XXX for now, no evcnt parent reported */
560 	return NULL;
561 }
562 
563 void *
564 pci_intr_establish(pc, ih, level, func, arg)
565 	pci_chipset_tag_t pc;
566 	pci_intr_handle_t ih;
567 	int level;
568 	int (*func) __P((void *));
569 	void *arg;
570 {
571 	void *cookie;
572 	struct psycho_pbm *pp = (struct psycho_pbm *)pc->cookie;
573 
574 	DPRINTF(SPDB_INTR, ("pci_intr_establish: ih %lu; level %d", (u_long)ih, level));
575 	cookie = bus_intr_establish(pp->pp_memt, ih, level, func, arg);
576 
577 	DPRINTF(SPDB_INTR, ("; returning handle %p\n", cookie));
578 	return (cookie);
579 }
580 
581 void
582 pci_intr_disestablish(pc, cookie)
583 	pci_chipset_tag_t pc;
584 	void *cookie;
585 {
586 
587 	DPRINTF(SPDB_INTR, ("pci_intr_disestablish: cookie %p\n", cookie));
588 
589 	/* XXX */
590 	panic("can't disestablish PCI interrupts yet");
591 }
592