xref: /openbsd-src/sys/arch/hppa/dev/mongoose.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: mongoose.c,v 1.17 2004/11/08 20:54:04 miod Exp $	*/
2 
3 /*
4  * Copyright (c) 1998-2003 Michael Shalayeff
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  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32 #include <sys/reboot.h>
33 
34 #include <machine/bus.h>
35 #include <machine/iomod.h>
36 #include <machine/autoconf.h>
37 
38 #include <hppa/dev/cpudevs.h>
39 #include <hppa/dev/viper.h>
40 
41 #include <dev/eisa/eisareg.h>
42 #include <dev/eisa/eisavar.h>
43 
44 #include <dev/isa/isareg.h>
45 #include <dev/isa/isavar.h>
46 
47 #include <hppa/dev/mongoosereg.h>
48 #include <hppa/dev/mongoosevar.h>
49 
50 void	mgattach_gedoens(struct device *, struct device *, void *);
51 int	mgmatch_gedoens(struct device *, void *, void *);
52 
53 struct cfattach mg_gedoens_ca = {
54 	sizeof(struct mongoose_softc), mgmatch_gedoens, mgattach_gedoens
55 };
56 
57 struct cfdriver mongoose_cd = {
58 	NULL, "mongoose", DV_DULL
59 };
60 
61 /* TODO: DMA guts */
62 
63 void
64 mg_eisa_attach_hook(struct device *parent, struct device *self,
65 	struct eisabus_attach_args *mg)
66 {
67 }
68 
69 int
70 mg_intr_map(void *v, u_int irq, eisa_intr_handle_t *ehp)
71 {
72 	*ehp = irq;
73 	return 0;
74 }
75 
76 const char *
77 mg_intr_string(void *v, int irq)
78 {
79 	static char buf[16];
80 
81 	snprintf(buf, sizeof buf, "isa irq %d", irq);
82 	return buf;
83 }
84 
85 void
86 mg_isa_attach_hook(struct device *parent, struct device *self,
87 	struct isabus_attach_args *iba)
88 {
89 
90 }
91 
92 void *
93 mg_intr_establish(void *v, int irq, int type, int pri,
94 	int (*handler)(void *), void *arg, const char *name)
95 {
96 	struct hppa_isa_iv *iv;
97 	struct mongoose_softc *sc = v;
98 	volatile u_int8_t *imr, *pic;
99 
100 	if (!sc || irq < 0 || irq >= MONGOOSE_NINTS ||
101 	    (0 <= irq && irq < MONGOOSE_NINTS && sc->sc_iv[irq].iv_handler))
102 		return NULL;
103 
104 	if (type != IST_LEVEL && type != IST_EDGE) {
105 #ifdef DEBUG
106 		printf("%s: bad interrupt level (%d)\n", sc->sc_dev.dv_xname,
107 		    type);
108 #endif
109 		return NULL;
110 	}
111 
112 	iv = &sc->sc_iv[irq];
113 	if (iv->iv_handler) {
114 #ifdef DEBUG
115 		printf("%s: irq %d already established\n", sc->sc_dev.dv_xname,
116 		    irq);
117 #endif
118 		return NULL;
119 	}
120 
121 	iv->iv_name = name;
122 	iv->iv_pri = pri;
123 	iv->iv_handler = handler;
124 	iv->iv_arg = arg;
125 
126 	if (irq < 8) {
127 		imr = &sc->sc_ctrl->imr0;
128 		pic = &sc->sc_ctrl->pic0;
129 	} else {
130 		imr = &sc->sc_ctrl->imr1;
131 		pic = &sc->sc_ctrl->pic1;
132 		irq -= 8;
133 	}
134 
135 	*imr |= 1 << irq;
136 	*pic |= (type == IST_LEVEL) << irq;
137 
138 	/* TODO: ack it? */
139 
140 	return iv;
141 }
142 
143 void
144 mg_intr_disestablish(void *v, void *cookie)
145 {
146 	struct hppa_isa_iv *iv = cookie;
147 	struct mongoose_softc *sc = v;
148  	int irq = iv - sc->sc_iv;
149  	volatile u_int8_t *imr;
150 
151 	if (!sc || !cookie)
152 		return;
153 
154 	if (irq < 8)
155 		imr = &sc->sc_ctrl->imr0;
156 	else
157 		imr = &sc->sc_ctrl->imr1;
158 	*imr &= ~(1 << irq);
159 	/* TODO: ack it? */
160 
161 	iv->iv_handler = NULL;
162 }
163 
164 int
165 mg_intr_check(void *v, int irq, int type)
166 {
167 	return 0;
168 }
169 
170 int
171 mg_intr(void *v)
172 {
173 	struct mongoose_softc *sc = v;
174 	struct hppa_isa_iv *iv;
175 	int s, irq = 0;
176 
177 	iv = &sc->sc_iv[irq];
178 	s = splraise(iv->iv_pri);
179 	(iv->iv_handler)(iv->iv_arg);
180 	splx(s);
181 
182 	return 0;
183 }
184 
185 int
186 mg_eisa_iomap(void *v, bus_addr_t addr, bus_size_t size, int cacheable,
187 	bus_space_handle_t *bshp)
188 {
189 	struct mongoose_softc *sc = v;
190 
191 	/* see if it's ISA space we are mapping */
192 	if (0x100 <= addr && addr < 0x400) {
193 #define	TOISA(a) ((((a) & 0x3f8) << 9) + ((a) & 7))
194 		size = TOISA(addr + size) - TOISA(addr);
195 		addr = TOISA(addr);
196 	}
197 
198 	return (sc->sc_bt->hbt_map)(NULL, sc->sc_iomap + addr, size,
199 				    cacheable, bshp);
200 }
201 
202 int
203 mg_eisa_memmap(void *v, bus_addr_t addr, bus_size_t size, int cacheable,
204 	bus_space_handle_t *bshp)
205 {
206 	/* TODO: eisa memory map */
207 	return -1;
208 }
209 
210 void
211 mg_eisa_memunmap(void *v, bus_space_handle_t bsh, bus_size_t size)
212 {
213 	/* TODO: eisa memory unmap */
214 }
215 
216 void
217 mg_isa_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
218 {
219 	sync_caches();
220 }
221 
222 u_int16_t
223 mg_isa_r2(void *v, bus_space_handle_t h, bus_size_t o)
224 {
225 	register u_int16_t r = *((volatile u_int16_t *)(h + o));
226 	return letoh16(r);
227 }
228 
229 u_int32_t
230 mg_isa_r4(void *v, bus_space_handle_t h, bus_size_t o)
231 {
232 	register u_int32_t r = *((volatile u_int32_t *)(h + o));
233 	return letoh32(r);
234 }
235 
236 void
237 mg_isa_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv)
238 {
239 	*((volatile u_int16_t *)(h + o)) = htole16(vv);
240 }
241 
242 void
243 mg_isa_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv)
244 {
245 	*((volatile u_int32_t *)(h + o)) = htole32(vv);
246 }
247 
248 void
249 mg_isa_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
250 {
251 	h += o;
252 	while (c--)
253 		*(a++) = letoh16(*(volatile u_int16_t *)h);
254 }
255 
256 void
257 mg_isa_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
258 {
259 	h += o;
260 	while (c--)
261 		*(a++) = letoh32(*(volatile u_int32_t *)h);
262 }
263 
264 void
265 mg_isa_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
266 {
267 	register u_int16_t r;
268 	h += o;
269 	while (c--) {
270 		r = *(a++);
271 		*(volatile u_int16_t *)h = htole16(r);
272 	}
273 }
274 
275 void
276 mg_isa_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
277 {
278 	register u_int32_t r;
279 	h += o;
280 	while (c--) {
281 		r = *(a++);
282 		*(volatile u_int32_t *)h = htole32(r);
283 	}
284 }
285 
286 void
287 mg_isa_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
288 {
289 	vv = htole16(vv);
290 	h += o;
291 	while (c--)
292 		*(volatile u_int16_t *)h = vv;
293 }
294 
295 void
296 mg_isa_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
297 {
298 	vv = htole32(vv);
299 	h += o;
300 	while (c--)
301 		*(volatile u_int32_t *)h = vv;
302 }
303 
304 void
305 mg_isa_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
306 {
307 	register u_int16_t r;
308 	h += o;
309 	while (c--) {
310 		r = *((volatile u_int16_t *)h)++;
311 		*(a++) = letoh16(r);
312 	}
313 }
314 
315 void
316 mg_isa_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
317 {
318 	register u_int32_t r;
319 	h += o;
320 	while (c--) {
321 		r = *((volatile u_int32_t *)h)++;
322 		*(a++) = letoh32(r);
323 	}
324 }
325 
326 void
327 mg_isa_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
328 {
329 	register u_int16_t r;
330 	h += o;
331 	while (c--) {
332 		r = *(a++);
333 		*((volatile u_int16_t *)h)++ = htole16(r);
334 	}
335 }
336 
337 void
338 mg_isa_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
339 {
340 	register u_int32_t r;
341 	h += o;
342 	while (c--) {
343 		r = *(a++);
344 		*((volatile u_int32_t *)h)++ = htole32(r);
345 	}
346 }
347 
348 void
349 mg_isa_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
350 {
351 	vv = htole16(vv);
352 	h += o;
353 	while (c--)
354 		*((volatile u_int16_t *)h)++ = vv;
355 }
356 
357 void
358 mg_isa_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
359 {
360 	vv = htole32(vv);
361 	h += o;
362 	while (c--)
363 		*((volatile u_int32_t *)h)++ = vv;
364 }
365 
366 int
367 mgattach_common(sc)
368 	struct mongoose_softc *sc;
369 {
370 	struct hppa_bus_space_tag *bt;
371 	union mongoose_attach_args ea;
372 	char brid[EISA_IDSTRINGLEN];
373 
374 	viper_eisa_en();
375 
376 	/* BUS RESET */
377 	sc->sc_ctrl->nmi_ext = MONGOOSE_NMI_BUSRESET;
378 	DELAY(1);
379 	sc->sc_ctrl->nmi_ext = 0;
380 	DELAY(100);
381 
382 	/* determine eisa board id */
383 	{
384 		u_int8_t id[4], *p;
385 		p = (u_int8_t *)(sc->sc_iomap + EISA_SLOTOFF_VID);
386 		id[0] = *p++;
387 		id[1] = *p++;
388 		id[2] = *p++;
389 		id[3] = *p++;
390 
391 		brid[0] = EISA_VENDID_0(id);
392 		brid[1] = EISA_VENDID_1(id);
393 		brid[2] = EISA_VENDID_2(id);
394 		brid[3] = EISA_PRODID_0(id + 2);
395 		brid[4] = EISA_PRODID_1(id + 2);
396 		brid[5] = EISA_PRODID_2(id + 2);
397 		brid[6] = EISA_PRODID_3(id + 2);
398 		brid[7] = '\0';
399 	}
400 
401 	printf (": %s rev %d, %d MHz\n", brid, sc->sc_regs->version,
402 		(sc->sc_regs->clock? 33 : 25));
403 	sc->sc_regs->liowait = 1;	/* disable isa wait states */
404 	sc->sc_regs->lock    = 1;	/* bus unlock */
405 
406 	/* attach EISA */
407 	sc->sc_ec.ec_v = sc;
408 	sc->sc_ec.ec_attach_hook = mg_eisa_attach_hook;
409 	sc->sc_ec.ec_intr_establish = mg_intr_establish;
410 	sc->sc_ec.ec_intr_disestablish = mg_intr_disestablish;
411 	sc->sc_ec.ec_intr_string = mg_intr_string;
412 	sc->sc_ec.ec_intr_map = mg_intr_map;
413 	/* inherit the bus tags for eisa from the mainbus */
414 	bt = &sc->sc_eiot;
415 	bcopy(sc->sc_bt, bt, sizeof(*bt));
416 	bt->hbt_cookie = sc;
417 	bt->hbt_map = mg_eisa_iomap;
418 #define	R(n)	bt->__CONCAT(hbt_,n) = &__CONCAT(mg_isa_,n)
419 	/* R(barrier); */
420 	R(r2); R(r4); R(w2); R(w4);
421 	R(rm_2);R(rm_4);R(wm_2);R(wm_4);R(sm_2);R(sm_4);
422 	R(rr_2);R(rr_4);R(wr_2);R(wr_4);R(sr_2);R(sr_4);
423 
424 	bt = &sc->sc_ememt;
425 	bcopy(sc->sc_bt, bt, sizeof(*bt));
426 	bt->hbt_cookie = sc;
427 	bt->hbt_map = mg_eisa_memmap;
428 	bt->hbt_unmap = mg_eisa_memunmap;
429 	/* attachment guts */
430 	ea.mongoose_eisa.eba_busname = "eisa";
431 	ea.mongoose_eisa.eba_iot = &sc->sc_eiot;
432 	ea.mongoose_eisa.eba_memt = &sc->sc_ememt;
433 	ea.mongoose_eisa.eba_dmat = NULL /* &sc->sc_edmat */;
434 	ea.mongoose_eisa.eba_ec = &sc->sc_ec;
435 	config_found((struct device *)sc, &ea.mongoose_eisa, mgprint);
436 
437 	sc->sc_ic.ic_v = sc;
438 	sc->sc_ic.ic_attach_hook = mg_isa_attach_hook;
439 	sc->sc_ic.ic_intr_establish = mg_intr_establish;
440 	sc->sc_ic.ic_intr_disestablish = mg_intr_disestablish;
441 	sc->sc_ic.ic_intr_check = mg_intr_check;
442 	/* inherit the bus tags for isa from the eisa */
443 	bt = &sc->sc_imemt;
444 	bcopy(&sc->sc_ememt, bt, sizeof(*bt));
445 	bt = &sc->sc_iiot;
446 	bcopy(&sc->sc_eiot, bt, sizeof(*bt));
447 	/* TODO: DMA tags */
448 	/* attachment guts */
449 	ea.mongoose_isa.iba_busname = "isa";
450 	ea.mongoose_isa.iba_iot = &sc->sc_iiot;
451 	ea.mongoose_isa.iba_memt = &sc->sc_imemt;
452 #if NISADMA > 0
453 	ea.mongoose_isa.iba_dmat = &sc->sc_idmat;
454 #endif
455 	ea.mongoose_isa.iba_ic = &sc->sc_ic;
456 	config_found((struct device *)sc, &ea.mongoose_isa, mgprint);
457 #undef	R
458 
459 	return (0);
460 }
461 
462 int
463 mgprint(aux, pnp)
464 	void *aux;
465 	const char *pnp;
466 {
467 	union mongoose_attach_args *ea = aux;
468 
469 	if (pnp)
470 		printf ("%s at %s", ea->mongoose_name, pnp);
471 
472 	return (UNCONF);
473 }
474 
475 int
476 mgmatch_gedoens(parent, cfdata, aux)
477 	struct device *parent;
478 	void *cfdata;
479 	void *aux;
480 {
481 	register struct confargs *ca = aux;
482 	/* struct cfdata *cf = cfdata; */
483 	bus_space_handle_t ioh;
484 
485 	if (ca->ca_type.iodc_type != HPPA_TYPE_BHA ||
486 	    (ca->ca_type.iodc_sv_model != HPPA_BHA_EISA &&
487 	     ca->ca_type.iodc_sv_model != HPPA_BHA_WEISA))
488 		return 0;
489 
490 	if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE,
491 	    IOMOD_HPASIZE, 0, &ioh))
492 		return 0;
493 
494 	/* XXX check EISA signature */
495 
496 	bus_space_unmap(ca->ca_iot, ioh, IOMOD_HPASIZE);
497 
498 	return 1;
499 }
500 
501 void
502 mgattach_gedoens(parent, self, aux)
503 	struct device *parent;
504 	struct device *self;
505 	void *aux;
506 {
507 	register struct confargs *ca = aux;
508 	register struct mongoose_softc *sc = (struct mongoose_softc *)self;
509 
510 	sc->sc_bt = ca->ca_iot;
511 	sc->sc_iomap = ca->ca_hpa;
512 	sc->sc_regs = (struct mongoose_regs *)(ca->ca_hpa + MONGOOSE_MONGOOSE);
513 	sc->sc_ctrl = (struct mongoose_ctrl *)(ca->ca_hpa + MONGOOSE_CTRL);
514 
515 	if (mgattach_common(sc) != 0)
516 		return;
517 
518 	/* attach interrupt */
519 	sc->sc_ih = cpu_intr_establish(IPL_HIGH, ca->ca_irq,
520 				       mg_intr, sc, sc->sc_dev.dv_xname);
521 }
522