xref: /netbsd/sys/arch/sparc/sparc/pci_machdep.c (revision bf9ec67e)
1 /*	$NetBSD: pci_machdep.c,v 1.5 2002/05/16 01:33:53 uwe Exp $ */
2 
3 /*
4  * Copyright (c) 1999, 2000 Matthew R. Green
5  * Copyright (c) 2001 Valeriy E. Ushakov
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * Machine-dependent PCI bits for PCI controller in microSPARC-IIep.
34  * References are to the microSPARC-IIep manual unless noted otherwise.
35  */
36 
37 #if defined(DEBUG) && !defined(SPARC_PCI_DEBUG)
38 #define SPARC_PCI_DEBUG
39 #endif
40 
41 #ifdef SPARC_PCI_DEBUG
42 #define SPDB_CONF	0x01
43 #define SPDB_INTR	0x04
44 #define SPDB_INTMAP	0x08
45 #define SPDB_INTFIX	0x10
46 #define SPDB_PROBE	0x20
47 int sparc_pci_debug = 0;
48 #define DPRINTF(l, s)	do { 			\
49 	if (sparc_pci_debug & (l))		\
50 		printf s;			\
51 } while (/* CONSTCOND */ 0)
52 #else
53 #define DPRINTF(l, s)
54 #endif
55 
56 #include <sys/types.h>
57 #include <sys/param.h>
58 #include <sys/time.h>
59 #include <sys/systm.h>
60 #include <sys/errno.h>
61 #include <sys/device.h>
62 #include <sys/malloc.h>
63 
64 #include <machine/bus.h>
65 #include <machine/autoconf.h>
66 #include <machine/openfirm.h>
67 
68 #include <machine/ctlreg.h>
69 #include <sparc/sparc/asm.h>
70 
71 #include <dev/pci/pcivar.h>
72 #include <dev/pci/pcireg.h>
73 
74 #include <dev/ofw/ofw_pci.h>
75 
76 #include <sparc/sparc/msiiepreg.h>
77 #include <sparc/sparc/msiiepvar.h>
78 
79 /*
80  * Table 9-1 (p. 129).
81  *   Configuration space access.  This goes via MMU bypass ASI.
82  */
83 #define PCI_MODE1_ADDRESS_REG_PA	0x30080000
84 #define	PCI_MODE1_DATA_REG_PA		0x300a0000
85 
86 /*
87  * Footnote 1 in Table 9-1 (p. 129):
88  *
89  *   Three least significant bits of the configuration data space
90  *   access must match those of the configuration address space access.
91  */
92 #define PCI_MODE1_DATA_REG_MASK	0x7
93 
94 
95 /*
96  * PROMs in ms-IIep systems just lie about PCI and EBus interrupts, so
97  * we just hardcode the wiring based on the model we are running on.
98  * Probably we can do some forth hacking in boot loader's prompatch
99  * (that's what it was introduced for), but for now it's way more
100  * simple to just hardcode it here.
101  */
102 
103 
104 struct mspcic_pci_intr_wiring {
105 	u_int		mpiw_bus;
106 	u_int		mpiw_device;
107 	u_int		mpiw_function;
108 	pci_intr_line_t	mpiw_line;
109 };
110 
111 static struct mspcic_pci_intr_wiring krups_pci_intr_wiring[] = {
112 	{ 0, 0, 1,    1 },	/* ethernet */
113 	{ 0, 1, 0,    2 },	/* vga */
114 };
115 
116 
117 struct mspcic_known_model {
118 	const char *model;
119 	struct mspcic_pci_intr_wiring *map;
120 	int mapsize;
121 };
122 
123 #define MSPCIC_MODEL_WIRING(name,map) \
124 	{ name, map, sizeof(map)/sizeof(map[0]) }
125 
126 static struct mspcic_known_model mspcic_known_models[] = {
127 	MSPCIC_MODEL_WIRING("SUNW,501-4267", krups_pci_intr_wiring),
128 	{ NULL, NULL, 0}
129 };
130 
131 
132 static struct mspcic_pci_intr_wiring *wiring_map;
133 static int wiring_map_size;
134 
135 
136 void
137 pci_attach_hook(parent, self, pba)
138 	struct device *parent;
139 	struct device *self;
140 	struct pcibus_attach_args *pba;
141 {
142 	struct mspcic_known_model *p;
143 	char buf[32];
144 	char *model;
145 
146 	model = PROM_getpropstringA(prom_findroot(), "model",
147 				    buf, sizeof(buf));
148 	if (model == NULL)
149 		panic("pci_attach_hook: no \"model\" property");
150 
151 	printf(": model %s", model);
152 
153 	for (p = mspcic_known_models; p->model != NULL; ++p)
154 		if (strcmp(model, p->model) == 0) {
155 			printf(": interrupt wiring known");
156 			wiring_map = p->map;
157 			wiring_map_size = p->mapsize;
158 			return;
159 		}
160 
161 	/* not found */
162 	printf(": don't know how interrupts are wired\n");
163 	panic("pci_attach_hook: unknown model %s", model);
164 }
165 
166 
167 int
168 pci_bus_maxdevs(pc, busno)
169 	pci_chipset_tag_t pc;
170 	int busno;
171 {
172 
173 	return (32);
174 }
175 
176 
177 pcitag_t
178 pci_make_tag(pc, b, d, f)
179 	pci_chipset_tag_t pc;
180 	int b;
181 	int d;
182 	int f;
183 {
184 	struct mspcic_softc *sc = (struct mspcic_softc *)pc->cookie;
185 	pcitag_t tag;
186 	int node, len;
187 #ifdef SPARC_PCI_DEBUG
188 	char name[80];
189 
190 	memset(name, 0, sizeof(name));
191 #endif
192 
193 	tag = PCITAG_CREATE(-1, b, d, f);
194 	if (b >= 256 || d >= 32 || f >= 8) {
195 		printf("pci_make_tag: bad request %d/%d/%d\n", b, d, f);
196 		return (tag); /* a dead one */
197 	}
198 
199 	/*
200 	 * XXX: OFW 3.11 doesn't have "bus-range" property on its
201 	 * "/pci" node.  As a workaround we start with the first child
202 	 * of "/pci" instead of matching the bus number against the
203 	 * "bus-range" of the "/pci" node.
204 	 *
205 	 * Traverse all peers until we find the node.
206 	 */
207 	for (node = OF_child(sc->sc_node); node != 0; node = OF_peer(node)) {
208 		struct ofw_pci_register reg;
209 		u_int32_t busrange[2];
210 
211 #ifdef SPARC_PCI_DEBUG
212 		if (sparc_pci_debug & SPDB_PROBE) {
213 			OF_getprop(node, "name", &name, sizeof(name));
214 			printf("> checking node %x %s\n", node, name);
215 		}
216 #endif
217 		/*
218 		 * Check for PCI-PCI bridges.  If the device we want is
219 		 * in the bus-range for that bridge, work our way down.
220 		 */
221 		while ((OF_getprop(node, "bus-range", (void *)&busrange,
222 				   sizeof(busrange)) == sizeof(busrange))
223 		       && (b >= busrange[0] && b <= busrange[1]))
224 		{
225 			/* go down one level */
226 			node = OF_child(node);
227 #ifdef SPARC_PCI_DEBUG
228 			if (sparc_pci_debug & SPDB_PROBE) {
229 				OF_getprop(node, "name", &name, sizeof(name));
230 				printf("> going down to node %x %s\n",
231 					node, name);
232 			}
233 #endif
234 		}
235 
236 		/*
237 		 * We only really need the first `reg' property.
238 		 *
239 		 * For simplicity, we'll query the `reg' when we
240 		 * need it.  Otherwise we could malloc() it, but
241 		 * that gets more complicated.
242 		 */
243 		len = OF_getproplen(node, "reg");
244 		if (len < sizeof(reg))
245 			continue;
246 		if (OF_getprop(node, "reg", (void *)&reg, sizeof(reg)) != len)
247 			panic("pci_probe_bus: OF_getprop len botch");
248 
249 		if (b != OFW_PCI_PHYS_HI_BUS(reg.phys_hi))
250 			continue;
251 		if (d != OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi))
252 			continue;
253 		if (f != OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi))
254 			continue;
255 
256 		/* Got a match */
257 		tag = PCITAG_CREATE(node, b, d, f);
258 
259 		/* Enable all the different spaces for this device */
260 		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
261 			PCI_COMMAND_MASTER_ENABLE
262 			| PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_IO_ENABLE);
263 		DPRINTF(SPDB_PROBE, ("> found node %x %s\n", node, name));
264 		return (tag);
265 	}
266 
267 	/* No device found - return a dead tag */
268 	return (tag);
269 }
270 
271 
272 void
273 pci_decompose_tag(pc, tag, bp, dp, fp)
274 	pci_chipset_tag_t pc;
275 	pcitag_t tag;
276 	int *bp, *dp, *fp;
277 {
278 	if (bp != NULL)
279 		*bp = PCITAG_BUS(tag);
280 	if (dp != NULL)
281 		*dp = PCITAG_DEV(tag);
282 	if (fp != NULL)
283 		*fp = PCITAG_FUN(tag);
284 }
285 
286 
287 pcireg_t
288 pci_conf_read(pc, tag, reg)
289 	pci_chipset_tag_t pc;
290 	pcitag_t tag;
291 	int reg;
292 {
293 	u_int32_t mode1_addr;
294 	u_int32_t mode1_data_reg_pa;
295 	pcireg_t val = (pcireg_t)~0;
296 
297 	DPRINTF(SPDB_CONF,
298 		("pci_conf_read:  tag=%x.%x (%d/%d/%d), reg=%02x; ",
299 		 PCITAG_NODE(tag), PCITAG_OFFSET(tag),
300 		 PCITAG_BUS(tag), PCITAG_DEV(tag), PCITAG_FUN(tag),
301 		 reg));
302 
303 #ifdef DIAGNOSTIC
304 	if (reg & 0x3)
305 		panic("pci_conf_read: reg %x unaligned", reg);
306 	if (reg & ~0xff)
307 		panic("pci_conf_read: reg %x out of range", reg);
308 #endif
309 
310 	if (PCITAG_NODE(tag) == -1) {
311 		DPRINTF(SPDB_CONF, ("\n"));
312 		return (val);
313 	}
314 
315 	mode1_addr = PCITAG_OFFSET(tag) | reg;
316 	mode1_data_reg_pa = PCI_MODE1_DATA_REG_PA
317 		| (reg & PCI_MODE1_DATA_REG_MASK);
318 
319 	/*
320 	 * NB: we run in endian-swapping mode, so we don't need to
321 	 * convert mode1_addr and val.
322 	 */
323 	sta(PCI_MODE1_ADDRESS_REG_PA, ASI_BYPASS, mode1_addr);
324 	val = lda(mode1_data_reg_pa, ASI_BYPASS);
325 
326 	DPRINTF(SPDB_CONF, ("reading %08x\n", (u_int)val));
327 
328 	return (val);
329 }
330 
331 
332 void
333 pci_conf_write(pc, tag, reg, data)
334 	pci_chipset_tag_t pc;
335 	pcitag_t tag;
336 	int reg;
337 	pcireg_t data;
338 {
339 	u_int32_t mode1_addr;
340 	u_int32_t mode1_data_reg_pa;
341 
342 	DPRINTF(SPDB_CONF,
343 		("pci_conf_write: tag=%x.%x (%d/%d/%d); reg=%02x; ",
344 		 PCITAG_NODE(tag), PCITAG_OFFSET(tag),
345 		 PCITAG_BUS(tag), PCITAG_DEV(tag), PCITAG_FUN(tag),
346 		 reg));
347 
348 #ifdef DIAGNOSTIC
349 	if (reg & 0x3)
350 		panic("pci_conf_write: reg %x unaligned", reg);
351 	if (reg & ~0xff)
352 		panic("pci_conf_write: reg %x out of range", reg);
353 #endif
354 
355 	if (PCITAG_NODE(tag) == -1) {
356 		DPRINTF(SPDB_CONF, ("\n"));
357 		return;
358 	}
359 
360 	mode1_addr = PCITAG_OFFSET(tag) | reg;
361 	mode1_data_reg_pa = PCI_MODE1_DATA_REG_PA
362 		| (reg & PCI_MODE1_DATA_REG_MASK);
363 
364 	DPRINTF(SPDB_CONF, ("writing %08x\n", data));
365 
366 	/*
367 	 * NB: we run in endian-swapping mode, so we don't need to
368 	 * convert mode1_addr and data.
369 	 */
370 	sta(PCI_MODE1_ADDRESS_REG_PA, ASI_BYPASS, mode1_addr);
371 	sta(mode1_data_reg_pa, ASI_BYPASS, data);
372 }
373 
374 
375 /* ======================================================================
376  *
377  *	       PCI bus interrupt manipulation functions
378  */
379 
380 int
381 pci_intr_map(pa, ihp)
382 	struct pci_attach_args *pa;
383 	pci_intr_handle_t *ihp;
384 {
385 	int i;
386 
387 	DPRINTF(SPDB_INTMAP,
388 		("pci_intr_map(%d/%d/%d) -> ",
389 		 pa->pa_bus, pa->pa_device, pa->pa_function));
390 
391 	for (i = 0; i < wiring_map_size; ++i) {
392 		struct mspcic_pci_intr_wiring *w = &wiring_map[i];
393 
394 		if (pa->pa_bus == w->mpiw_bus
395 		    && pa->pa_device == w->mpiw_device
396 		    && pa->pa_function == w->mpiw_function)
397 		{
398 			DPRINTF(SPDB_INTMAP, ("line %d\n", w->mpiw_line));
399 			*ihp = w->mpiw_line;
400 			return (0);
401 		}
402 	}
403 
404 	DPRINTF(SPDB_INTMAP, ("not found\n"));
405 	return (-1);
406 }
407 
408 
409 const char *
410 pci_intr_string(pc, ih)
411 	pci_chipset_tag_t pc;
412 	pci_intr_handle_t ih;
413 {
414 	static char str[16];
415 	int pil;
416 
417 	pil = mspcic_assigned_interrupt(ih);
418 	sprintf(str, "line %d (pil %d)", ih, pil);
419 	return (str);
420 }
421 
422 
423 const struct evcnt *
424 pci_intr_evcnt(pc, ih)
425 	pci_chipset_tag_t pc;
426 	pci_intr_handle_t ih;
427 {
428 
429 	/* XXX for now, no evcnt parent reported */
430 	return NULL;
431 }
432 
433 
434 void *
435 pci_intr_establish(pc, ih, level, func, arg)
436 	pci_chipset_tag_t pc;
437 	pci_intr_handle_t ih;
438 	int level;
439 	int (*func)(void *);
440 	void *arg;
441 {
442 	struct mspcic_softc *sc = (struct mspcic_softc *)pc->cookie;
443 	void *cookie = NULL;
444 
445 	DPRINTF(SPDB_INTR,
446 		("pci_intr_establish(line %d, ipl %d)\n", ih, level));
447 
448 	cookie = bus_intr_establish(sc->sc_memt, ih, level, 0, func, arg);
449 
450 	/*
451 	 * TODO: to implement pci_intr_disestablish we need to capture
452 	 * the 'intrhand' returned by bus_intr_establish above and the
453 	 * pil the handler was established for, but we don't need to
454 	 * disestablish pci interrupts for now (and I doubt we will),
455 	 * so why bother.
456 	 */
457 
458 	DPRINTF(SPDB_INTR,
459 		("pci_intr_establish: returning handle %p\n", cookie));
460 	return (cookie);
461 }
462 
463 
464 void
465 pci_intr_disestablish(pc, cookie)
466 	pci_chipset_tag_t pc;
467 	void *cookie;
468 {
469 
470 	DPRINTF(SPDB_INTR, ("pci_intr_disestablish: cookie %p\n", cookie));
471 	panic("pci_intr_disestablish: not implemented");
472 }
473