xref: /netbsd-src/sys/arch/sandpoint/pci/pci_machdep.c (revision 9fbd88883c38d0c0fbfcbe66d76fe6b0fab3f9de)
1 /*	$NetBSD: pci_machdep.c,v 1.7 2001/10/29 23:37:37 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
5  * Copyright (c) 1994 Charles M. Hannum.  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. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by Charles M. Hannum.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Machine-specific functions for PCI autoconfiguration.
35  *
36  * On PCs, there are two methods of generating PCI configuration cycles.
37  * We try to detect the appropriate mechanism for this machine and set
38  * up a few function pointers to access the correct method directly.
39  *
40  * The configuration method can be hard-coded in the config file by
41  * using `options PCI_CONF_MODE=N', where `N' is the configuration mode
42  * as defined section 3.6.4.1, `Generating Configuration Cycles'.
43  */
44 #include "opt_openpic.h"
45 
46 #include <sys/types.h>
47 #include <sys/param.h>
48 #include <sys/device.h>
49 #include <sys/errno.h>
50 #include <sys/extent.h>
51 #include <sys/malloc.h>
52 #include <sys/queue.h>
53 #include <sys/systm.h>
54 #include <sys/time.h>
55 
56 #include <uvm/uvm.h>
57 
58 #define _POWERPC_BUS_DMA_PRIVATE
59 #include <machine/bus.h>
60 #include <machine/pio.h>
61 #include <machine/intr.h>
62 
63 #include <dev/isa/isavar.h>
64 #include <dev/pci/pcivar.h>
65 #include <dev/pci/pcireg.h>
66 #include <dev/pci/pciconf.h>
67 
68 #include <sandpoint/isa/icu.h>
69 
70 struct powerpc_bus_dma_tag pci_bus_dma_tag = {
71 	0,			/* _bounce_thresh */
72 	_bus_dmamap_create,
73 	_bus_dmamap_destroy,
74 	_bus_dmamap_load,
75 	_bus_dmamap_load_mbuf,
76 	_bus_dmamap_load_uio,
77 	_bus_dmamap_load_raw,
78 	_bus_dmamap_unload,
79 	NULL,			/* _dmamap_sync */
80 	_bus_dmamem_alloc,
81 	_bus_dmamem_free,
82 	_bus_dmamem_map,
83 	_bus_dmamem_unmap,
84 	_bus_dmamem_mmap,
85 };
86 
87 #define	PCI_CONFIG_ENABLE	0x80000000UL
88 
89 void
90 pci_attach_hook(parent, self, pba)
91 	struct device *parent, *self;
92 	struct pcibus_attach_args *pba;
93 {
94 }
95 
96 int
97 pci_bus_maxdevs(pc, busno)
98 	pci_chipset_tag_t pc;
99 	int busno;
100 {
101 
102 	/*
103 	 * Bus number is irrelevant.  Configuration Mechanism 1 is in
104 	 * use, can have devices 0-32 (i.e. the `normal' range).
105 	 */
106 	return (32);
107 }
108 
109 pcitag_t
110 pci_make_tag(pc, bus, device, function)
111 	pci_chipset_tag_t pc;
112 	int bus, device, function;
113 {
114 	pcitag_t tag;
115 
116 	if (bus >= 256 || device >= 32 || function >= 8)
117 		panic("pci_make_tag: bad request");
118 
119 	tag = PCI_CONFIG_ENABLE |
120 		    (bus << 16) | (device << 11) | (function << 8);
121 	return tag;
122 }
123 
124 void
125 pci_decompose_tag(pc, tag, bp, dp, fp)
126 	pci_chipset_tag_t pc;
127 	pcitag_t tag;
128 	int *bp, *dp, *fp;
129 {
130 
131 	if (bp != NULL)
132 		*bp = (tag >> 16) & 0xff;
133 	if (dp != NULL)
134 		*dp = (tag >> 11) & 0x1f;
135 	if (fp != NULL)
136 		*fp = (tag >> 8) & 0x7;
137 	return;
138 }
139 
140 /*
141  * The Kahlua documentation says that "reg" should be left-shifted by two
142  * and be in bits 2-7.  Apparently not.  It doesn't work that way, and the
143  * DINK32 ROM doesn't do it that way (I peeked at 0xfec00000 after running
144  * the DINK32 "pcf" command).
145  */
146 #define SP_PCI(tag, reg) ((tag) | (reg))
147 
148 pcireg_t
149 pci_conf_read(pc, tag, reg)
150 	pci_chipset_tag_t pc;
151 	pcitag_t tag;
152 	int reg;
153 {
154 	pcireg_t data;
155 
156 	out32rb(SANDPOINT_PCI_CONFIG_ADDR, SP_PCI(tag,reg));
157 	data = in32rb(SANDPOINT_PCI_CONFIG_DATA);
158 	out32rb(SANDPOINT_PCI_CONFIG_ADDR, 0);
159 	return data;
160 }
161 
162 void
163 pci_conf_write(pc, tag, reg, data)
164 	pci_chipset_tag_t pc;
165 	pcitag_t tag;
166 	int reg;
167 	pcireg_t data;
168 {
169 	out32rb(SANDPOINT_PCI_CONFIG_ADDR, SP_PCI(tag, reg));
170 	out32rb(SANDPOINT_PCI_CONFIG_DATA, data);
171 	out32rb(SANDPOINT_PCI_CONFIG_ADDR, 0);
172 }
173 
174 int
175 pci_intr_map(pa, ihp)
176 	struct pci_attach_args *pa;
177 	pci_intr_handle_t *ihp;
178 {
179 	int	pin = pa->pa_intrpin;
180 	int	line = pa->pa_intrline;
181 
182 	if (pin == 0) {
183 		/* No IRQ used. */
184 		goto bad;
185 	}
186 
187 	if (pin > 4) {
188 		printf("pci_intr_map: bad interrupt pin %d\n", pin);
189 		goto bad;
190 	}
191 
192 	/*
193 	 * Section 6.2.4, `Miscellaneous Functions', says that 255 means
194 	 * `unknown' or `no connection' on a PC.  We assume that a device with
195 	 * `no connection' either doesn't have an interrupt (in which case the
196 	 * pin number should be 0, and would have been noticed above), or
197 	 * wasn't configured by the BIOS (in which case we punt, since there's
198 	 * no real way we can know how the interrupt lines are mapped in the
199 	 * hardware).
200 	 *
201 	 * XXX
202 	 * Since IRQ 0 is only used by the clock, and we can't actually be sure
203 	 * that the BIOS did its job, we also recognize that as meaning that
204 	 * the BIOS has not configured the device.
205 	 */
206 	if (line == 255) {
207 		printf("pci_intr_map: no mapping for pin %c\n", '@' + pin);
208 		goto bad;
209 	} else {
210 		/*
211 		 * Sandpoint has 4 PCI slots.
212 		 * Sandpoint rev. X2 has them in a weird order.  Counting
213 		 * from center out toward the edge, we have:
214 		 * 	Slot 1 (dev 14?) (labelled 1)
215 		 * 	Slot 0 (dev 13?) (labelled 2)
216 		 * 	Slot 3 (dev 16)  (labelled 3)
217 		 * 	Slot 2 (dev 15)  (labelled 4)
218 		 * To keep things confusing, we will consistently use a zero-
219 		 * based numbering scheme where Motorola's is usually 1-based.
220 		 */
221 		if (line < 13 || line > 16) {
222 			printf("pci_intr_map: bad interrupt line %d\n", line);
223 			goto bad;
224 		}
225 	}
226 	/*
227 	 * In the PCI configuration code, we simply assign the dev
228 	 * number to the interrupt line.  We extract it here for the
229 	 * interrupt, but subtract off the lowest dev (13) to get
230 	 * the IRQ.
231 	 */
232 #if defined(OPENPIC_SERIAL_MODE)
233 	line -= 11;
234 #else
235 	line -= 13;
236 #endif
237 
238 	*ihp = line;
239 	return 0;
240 
241 bad:
242 	*ihp = -1;
243 	return 1;
244 }
245 
246 const char *
247 pci_intr_string(pc, ih)
248 	pci_chipset_tag_t pc;
249 	pci_intr_handle_t ih;
250 {
251 	static char irqstr[8];		/* 4 + 2 + NULL + sanity */
252 
253 	if (ih < 0 || ih >= ICU_LEN)
254 		panic("pci_intr_string: bogus handle 0x%x\n", ih);
255 
256 	sprintf(irqstr, "irq %d", ih);
257 	return (irqstr);
258 
259 }
260 
261 const struct evcnt *
262 pci_intr_evcnt(pc, ih)
263 	pci_chipset_tag_t pc;
264 	pci_intr_handle_t ih;
265 {
266 
267 	/* XXX for now, no evcnt parent reported */
268 	return NULL;
269 }
270 
271 void *
272 pci_intr_establish(pc, ih, level, func, arg)
273 	pci_chipset_tag_t pc;
274 	pci_intr_handle_t ih;
275 	int level, (*func) __P((void *));
276 	void *arg;
277 {
278 #if 0
279 	if (ih < SANDPOINT_INTR_PCI0 || ih > SANDPOINT_INTR_PCI3)
280 		panic("pci_intr_establish: bogus handle 0x%x\n", ih);
281 #endif
282 
283 	/*
284 	 * ih is the value assigned in pci_intr_map(), above.
285 	 * For the Sandpoint, this is the zero-based slot #,
286 	 * configured when the bus is set up.
287 	 */
288 	return intr_establish(ih, IST_LEVEL, level, func, arg);
289 }
290 
291 void
292 pci_intr_disestablish(pc, cookie)
293 	pci_chipset_tag_t pc;
294 	void *cookie;
295 {
296 	intr_disestablish(cookie);
297 }
298 
299 void
300 pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int pin, int swiz,
301     int *iline)
302 {
303 	if (bus == 0) {
304 		*iline = dev;
305 	} else {
306 		/*
307 		 * If we are not on bus zero, we're behind a bridge, so we
308 		 * swizzle.
309 		 *
310 		 * The documentation lies about this.  In slot 3 (numbering
311 		 * from 0) aka device 16, INTD# becomes an interrupt for
312 		 * slot 2.  INTC# becomes an interrupt for slot 1, etc.
313 		 * In slot 2 aka device 16, INTD# becomes an interrupt for
314 		 * slot 1, etc.
315 		 *
316 		 * Verified for INTD# on device 16, INTC# on device 16,
317 		 * INTD# on device 15, INTD# on device 13, and INTC# on
318 		 * device 14.  I presume that the rest follow the same
319 		 * pattern.
320 		 *
321 		 * Slot 0 is device 13, and is the base for the rest.
322 		 */
323 		*iline = 13 + ((swiz + dev + 3) & 3);
324 	}
325 }
326