xref: /openbsd/sys/arch/macppc/pci/macobio.c (revision 891d7ab6)
1 /*	$OpenBSD: macobio.c,v 1.19 2011/05/15 09:10:26 mpi Exp $	*/
2 /*	$NetBSD: obio.c,v 1.6 1999/05/01 10:36:08 tsubai Exp $	*/
3 
4 /*-
5  * Copyright (C) 1998	Internet Research Institute, Inc.
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. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by
19  *	Internet Research Institute, Inc.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 
41 #include <dev/pci/pcivar.h>
42 #include <dev/pci/pcidevs.h>
43 
44 #include <dev/ofw/openfirm.h>
45 
46 #include <machine/bus.h>
47 #include <machine/autoconf.h>
48 #include <macppc/pci/macobio.h>
49 
50 void macobio_attach(struct device *, struct device *, void *);
51 int macobio_match(struct device *, void *, void *);
52 int macobio_print(void *, const char *);
53 void macobio_modem_power(int enable);
54 
55 void *undef_mac_establish(void * lcv, int irq, int type, int level,
56     int (*ih_fun)(void *), void *ih_arg, const char *name);
57 void mac_intr_disestab(void *lcp, void *arg);
58 
59 struct macobio_softc {
60 	struct device sc_dev;
61 	int sc_node;
62 	struct ppc_bus_space sc_membus_space;
63 	int	sc_id; /* copy of the PCI pa_id */
64 	u_int8_t *obiomem;
65 };
66 struct cfdriver macobio_cd = {
67 	NULL, "macobio", DV_DULL,
68 };
69 
70 
71 struct cfattach macobio_ca = {
72 	sizeof(struct macobio_softc), macobio_match, macobio_attach
73 };
74 
75 int
76 macobio_match(struct device *parent, void *cf, void *aux)
77 {
78 	struct pci_attach_args *pa = aux;
79 
80 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_APPLE)
81 		switch (PCI_PRODUCT(pa->pa_id)) {
82 
83 		case PCI_PRODUCT_APPLE_GC:
84 		case PCI_PRODUCT_APPLE_OHARE:
85 		case PCI_PRODUCT_APPLE_HEATHROW:
86 		case PCI_PRODUCT_APPLE_PADDINGTON:
87 		case PCI_PRODUCT_APPLE_KEYLARGO:
88 		case PCI_PRODUCT_APPLE_INTREPID:
89 		case PCI_PRODUCT_APPLE_PANGEA_MACIO:
90 		case PCI_PRODUCT_APPLE_SHASTA:
91 		case PCI_PRODUCT_APPLE_K2_MACIO:
92 			return 1;
93 		}
94 
95 	return 0;
96 }
97 
98 #define HEATHROW_FCR_OFFSET 0x38
99 u_int32_t *heathrow_FCR = NULL;
100 
101 /*
102  * Attach all the sub-devices we can find
103  */
104 void
105 macobio_attach(struct device *parent, struct device *self, void *aux)
106 {
107 	struct macobio_softc *sc = (struct macobio_softc *)self;
108 	struct pci_attach_args *pa = aux;
109 	struct confargs ca;
110 	int node, child, namelen;
111 	u_int32_t reg[20];
112 	int32_t intr[8];
113 	char name[32];
114 	int need_interrupt_controller = 0;
115 
116 	sc->sc_id = pa->pa_id; /* save of type for later */
117 
118 	switch (PCI_PRODUCT(pa->pa_id)) {
119 
120 	/* XXX should not use name */
121 	case PCI_PRODUCT_APPLE_GC:
122 		node = OF_finddevice("/bandit/gc");
123 		need_interrupt_controller = 1;
124 		break;
125 
126 	case PCI_PRODUCT_APPLE_OHARE:
127 		node = OF_finddevice("/bandit/ohare");
128 		need_interrupt_controller = 1;
129 		break;
130 
131 	case PCI_PRODUCT_APPLE_HEATHROW:
132 	case PCI_PRODUCT_APPLE_PADDINGTON:
133 		node = OF_finddevice("mac-io");
134 		if (node == -1)
135 			node = OF_finddevice("/pci/mac-io");
136 		if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg))
137 			== (sizeof (reg[0]) * 5))
138 		{
139 			/* always ??? */
140 			heathrow_FCR = mapiodev(reg[2] + HEATHROW_FCR_OFFSET,
141 			    4);
142 		}
143 		break;
144 	case PCI_PRODUCT_APPLE_KEYLARGO:
145 	case PCI_PRODUCT_APPLE_INTREPID:
146 	case PCI_PRODUCT_APPLE_PANGEA_MACIO:
147 	case PCI_PRODUCT_APPLE_SHASTA:
148 	case PCI_PRODUCT_APPLE_K2_MACIO:
149 		node = OF_finddevice("mac-io");
150 		if (node == -1)
151 			node = OF_finddevice("/pci/mac-io");
152 		if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg))
153 		    == (sizeof (reg[0]) * 5))
154 			 sc->obiomem = mapiodev(reg[2], 0x100);
155 		break;
156 	default:
157 		printf(": unknown macobio controller\n");
158 		return;
159 	}
160 	sc->sc_node = node;
161 
162 	if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg)) < 12)
163 		return;
164 
165 	ca.ca_baseaddr = reg[2];
166 
167 	sc->sc_membus_space.bus_base = ca.ca_baseaddr;
168 
169 	ca.ca_iot = &sc->sc_membus_space;
170 	ca.ca_dmat = pa->pa_dmat;
171 
172 	printf("\n");
173 
174 	/*
175 	 * This might be a hack, but it makes the interrupt controller
176 	 * attach as expected if a device node existed in the OF tree.
177 	 */
178 	if (need_interrupt_controller) {
179 		/* force attachment of legacy interrupt controllers */
180 		ca.ca_name = "legacy-interrupt-controller";
181 		ca.ca_node = 0;
182 
183 		ca.ca_nreg  = 0;
184 		ca.ca_nintr = 0;
185 
186 		ca.ca_reg = NULL;
187 		ca.ca_intr = NULL;
188 
189 		config_found(self, &ca, macobio_print);
190 	}
191 
192 	for (child = OF_child(node); child; child = OF_peer(child)) {
193 		namelen = OF_getprop(child, "name", name, sizeof(name));
194 		if (namelen < 0)
195 			continue;
196 		if (namelen >= sizeof(name))
197 			continue;
198 
199 		name[namelen] = 0;
200 		ca.ca_name = name;
201 		ca.ca_node = child;
202 
203 		ca.ca_nreg  = OF_getprop(child, "reg", reg, sizeof(reg));
204 		ca.ca_nintr = OF_getprop(child, "AAPL,interrupts", intr,
205 				sizeof(intr));
206 		if (ca.ca_nintr == -1)
207 			ca.ca_nintr = OF_getprop(child, "interrupts", intr,
208 					sizeof(intr));
209 
210 		ca.ca_reg = reg;
211 		ca.ca_intr = intr;
212 
213 		config_found(self, &ca, macobio_print);
214 	}
215 }
216 
217 int
218 macobio_print(void *aux, const char *macobio)
219 {
220 	struct confargs *ca = aux;
221 
222 	if (macobio)
223 		printf("\"%s\" at %s", ca->ca_name, macobio);
224 
225 	if (ca->ca_nreg > 0)
226 		printf(" offset 0x%x", ca->ca_reg[0]);
227 
228 	return UNCONF;
229 }
230 
231 void *
232 undef_mac_establish(void * lcv, int irq, int type, int level,
233     int (*ih_fun)(void *), void *ih_arg, const char *name)
234 {
235 	printf("mac_intr_establish called, not yet inited\n");
236 	return 0;
237 }
238 
239 void
240 mac_intr_disestab(void *lcp, void *arg)
241 {
242 	printf("mac_intr_disestablish called, not yet inited\n");
243 }
244 
245 intr_establish_t *mac_intr_establish_func = undef_mac_establish;
246 intr_disestablish_t *mac_intr_disestablish_func = mac_intr_disestab;
247 
248 void *
249 mac_intr_establish(void * lcv, int irq, int type, int level,
250     int (*ih_fun)(void *), void *ih_arg, const char *name)
251 {
252 	return (*mac_intr_establish_func)(lcv, irq, type, level, ih_fun,
253 	    ih_arg, name);
254 }
255 void
256 mac_intr_disestablish(void *lcp, void *arg)
257 {
258 	(*mac_intr_disestablish_func)(lcp, arg);
259 }
260 
261 void
262 macobio_enable(int offset, u_int32_t bits)
263 {
264 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
265 	if (sc->obiomem == 0)
266 		return;
267 
268 	bits |=  in32rb(sc->obiomem + offset);
269 	out32rb(sc->obiomem + offset, bits);
270 }
271 void
272 macobio_disable(int offset, u_int32_t bits)
273 {
274 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
275 	if (sc->obiomem == 0)
276 		return;
277 
278 	bits =  in32rb(sc->obiomem + offset) & ~bits;
279 	out32rb(sc->obiomem + offset, bits);
280 }
281 
282 u_int32_t
283 macobio_read(int offset)
284 {
285 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
286 	if (sc->obiomem == 0)
287 		return -1;
288 
289 	return in32rb(sc->obiomem + offset);
290 }
291 
292 void
293 macobio_write(int offset, u_int32_t bits)
294 {
295 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
296 	if (sc->obiomem == 0)
297 		return;
298 
299 	out32rb(sc->obiomem + offset, bits);
300 }
301 
302 void
303 macobio_modem_power(int enable)
304 {
305 	u_int32_t val;
306 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
307 	if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_KEYLARGO ||
308 	    PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_INTREPID) {
309 		val = in32rb(sc->obiomem + 0x40);
310 		if (enable)
311 			val = val & ~((u_int32_t)1<<25);
312 		else
313 			val = val | ((u_int32_t)1<<25);
314 		out32rb(sc->obiomem + 0x40, val);
315 	}
316 	if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_PANGEA_MACIO) {
317 		if (enable) {
318 			/* set reset */
319 			out8(sc->obiomem + 0x006a + 0x03, 0x04);
320 			/* power modem on */
321 			out8(sc->obiomem + 0x006a + 0x02, 0x04);
322 			/* unset reset */
323 			out8(sc->obiomem + 0x006a + 0x03, 0x05);
324 		}  else {
325 			/* disable it how? */
326 		}
327 	}
328 }
329