xref: /openbsd-src/sys/arch/alpha/tc/ioasic.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /* $OpenBSD: ioasic.c,v 1.17 2010/09/20 06:33:46 matthew Exp $ */
2 /* $NetBSD: ioasic.c,v 1.34 2000/07/18 06:10:06 thorpej Exp $ */
3 
4 /*-
5  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10  * NASA Ames Research Center.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
36  * All rights reserved.
37  *
38  * Author: Keith Bostic, Chris G. Demetriou
39  *
40  * Permission to use, copy, modify and distribute this software and
41  * its documentation is hereby granted, provided that both the copyright
42  * notice and this permission notice appear in all copies of the
43  * software, derivative works or modified versions, and any portions
44  * thereof, and that both notices appear in supporting documentation.
45  *
46  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
47  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
48  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49  *
50  * Carnegie Mellon requests users of this software to return to
51  *
52  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
53  *  School of Computer Science
54  *  Carnegie Mellon University
55  *  Pittsburgh PA 15213-3890
56  *
57  * any improvements or extensions that they make and grant Carnegie the
58  * rights to redistribute these changes.
59  */
60 
61 #include <sys/param.h>
62 #include <sys/kernel.h>
63 #include <sys/systm.h>
64 #include <sys/device.h>
65 #include <sys/malloc.h>
66 #include <sys/timeout.h>
67 
68 #include <machine/autoconf.h>
69 #include <machine/bus.h>
70 #include <machine/pte.h>
71 #include <machine/rpb.h>
72 
73 #include <dev/tc/tcvar.h>
74 #include <dev/tc/ioasicreg.h>
75 #include <dev/tc/ioasicvar.h>
76 #ifdef DEC_3000_300
77 #include <alpha/tc/tc_3000_300.h>
78 #endif
79 
80 /* Definition of the driver for autoconfig. */
81 int	ioasicmatch(struct device *, void *, void *);
82 void	ioasicattach(struct device *, struct device *, void *);
83 
84 struct cfattach ioasic_ca = {
85 	sizeof(struct ioasic_softc), ioasicmatch, ioasicattach,
86 };
87 
88 struct cfdriver ioasic_cd = {
89 	NULL, "ioasic", DV_DULL,
90 };
91 
92 int	ioasic_intr(void *);
93 int	ioasic_intrnull(void *);
94 
95 #define	C(x)	((void *)(u_long)(x))
96 #define	KV(x)	(ALPHA_PHYS_TO_K0SEG(x))
97 
98 #define	IOASIC_DEV_LANCE	0
99 #define	IOASIC_DEV_SCC0		1
100 #define	IOASIC_DEV_SCC1		2
101 #define	IOASIC_DEV_ISDN		3
102 
103 #define	IOASIC_DEV_BOGUS	-1
104 
105 #define	IOASIC_NCOOKIES		4
106 
107 struct ioasic_dev ioasic_devs[] = {
108 	{ "PMAD-BA ", IOASIC_SLOT_3_START, C(IOASIC_DEV_LANCE),
109 	  IOASIC_INTR_LANCE, },
110 	{ "z8530   ", IOASIC_SLOT_4_START, C(IOASIC_DEV_SCC0),
111 	  IOASIC_INTR_SCC_0, },
112 	{ "z8530   ", IOASIC_SLOT_6_START, C(IOASIC_DEV_SCC1),
113 	  IOASIC_INTR_SCC_1, },
114 	{ "TOY_RTC ", IOASIC_SLOT_8_START, C(IOASIC_DEV_BOGUS),
115 	  0, },
116 	{ "AMD79c30", IOASIC_SLOT_9_START, C(IOASIC_DEV_ISDN),
117 	  IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD,  },
118 };
119 int ioasic_ndevs = sizeof(ioasic_devs) / sizeof(ioasic_devs[0]);
120 
121 struct ioasicintr {
122 	int	(*iai_func)(void *);
123 	void	*iai_arg;
124 	struct evcount iai_count;
125 } ioasicintrs[IOASIC_NCOOKIES];
126 
127 tc_addr_t ioasic_base;		/* XXX XXX XXX */
128 
129 /* There can be only one. */
130 int ioasicfound;
131 
132 int
133 ioasicmatch(parent, cfdata, aux)
134 	struct device *parent;
135 	void *cfdata, *aux;
136 {
137 	struct tc_attach_args *ta = aux;
138 
139 	/* Make sure that we're looking for this type of device. */
140 	if (strncmp("FLAMG-IO", ta->ta_modname, TC_ROM_LLEN))
141 		return (0);
142 
143 	/* Check that it can actually exist. */
144 	if ((cputype != ST_DEC_3000_500) && (cputype != ST_DEC_3000_300))
145 		panic("ioasicmatch: how did we get here?");
146 
147 	if (ioasicfound)
148 		return (0);
149 
150 	return (1);
151 }
152 
153 void
154 ioasicattach(parent, self, aux)
155 	struct device *parent, *self;
156 	void *aux;
157 {
158 	struct ioasic_softc *sc = (struct ioasic_softc *)self;
159 	struct tc_attach_args *ta = aux;
160 #ifdef DEC_3000_300
161 	u_long ssr;
162 #endif
163 	u_long i, imsk;
164 
165 	ioasicfound = 1;
166 
167 	sc->sc_bst = ta->ta_memt;
168 	if (bus_space_map(ta->ta_memt, ta->ta_addr,
169 			0x400000, 0, &sc->sc_bsh)) {
170 		printf("%s: unable to map device\n", sc->sc_dv.dv_xname);
171 		return;
172 	}
173 	sc->sc_dmat = ta->ta_dmat;
174 
175 	ioasic_base = sc->sc_base = ta->ta_addr; /* XXX XXX XXX */
176 
177 #ifdef DEC_3000_300
178 	if (cputype == ST_DEC_3000_300) {
179 		ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
180 		ssr |= IOASIC_CSR_FASTMODE;
181 		bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
182 		printf(": slow mode\n");
183 	} else
184 #endif
185 		printf(": fast mode\n");
186 
187 	/*
188 	 * Turn off all device interrupt bits.
189 	 * (This does _not_ include 3000/300 TC option slot bits).
190 	 */
191 	imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK);
192 	for (i = 0; i < ioasic_ndevs; i++)
193 		imsk &= ~ioasic_devs[i].iad_intrbits;
194 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk);
195 
196 	/*
197 	 * Set up interrupt handlers.
198 	 */
199 	for (i = 0; i < IOASIC_NCOOKIES; i++) {
200 		ioasicintrs[i].iai_func = ioasic_intrnull;
201 		ioasicintrs[i].iai_arg = (void *)i;
202 	}
203 	tc_intr_establish(parent, ta->ta_cookie, IPL_NONE, ioasic_intr, sc,
204 	    NULL);
205 
206 	/*
207 	 * Try to configure each device.
208 	 */
209 	ioasic_attach_devs(sc, ioasic_devs, ioasic_ndevs);
210 }
211 
212 void
213 ioasic_intr_establish(ioa, cookie, level, func, arg, name)
214 	struct device *ioa;
215 	void *cookie, *arg;
216 	int level;
217 	int (*func)(void *);
218 	const char *name;
219 {
220 	struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0];
221 	u_long dev, i, imsk;
222 
223 	dev = (u_long)cookie;
224 #ifdef DIAGNOSTIC
225 	/* XXX check cookie. */
226 #endif
227 
228 	if (ioasicintrs[dev].iai_func != ioasic_intrnull)
229 		panic("ioasic_intr_establish: cookie %lu twice", dev);
230 
231 	ioasicintrs[dev].iai_func = func;
232 	ioasicintrs[dev].iai_arg = arg;
233 	evcount_attach(&ioasicintrs[dev].iai_count, name, NULL);
234 
235 	/* Enable interrupts for the device. */
236 	for (i = 0; i < ioasic_ndevs; i++)
237 		if (ioasic_devs[i].iad_cookie == cookie)
238 			break;
239 	if (i == ioasic_ndevs)
240 		panic("ioasic_intr_establish: invalid cookie.");
241 
242 	imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK);
243         imsk |= ioasic_devs[i].iad_intrbits;
244         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk);
245 }
246 
247 void
248 ioasic_intr_disestablish(ioa, cookie)
249 	struct device *ioa;
250 	void *cookie;
251 {
252 	struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0];
253 	u_long dev, i, imsk;
254 
255 	dev = (u_long)cookie;
256 #ifdef DIAGNOSTIC
257 	/* XXX check cookie. */
258 #endif
259 
260 	if (ioasicintrs[dev].iai_func == ioasic_intrnull)
261 		panic("ioasic_intr_disestablish: cookie %lu missing intr", dev);
262 
263 	/* Enable interrupts for the device. */
264 	for (i = 0; i < ioasic_ndevs; i++)
265 		if (ioasic_devs[i].iad_cookie == cookie)
266 			break;
267 	if (i == ioasic_ndevs)
268 		panic("ioasic_intr_disestablish: invalid cookie.");
269 
270 	imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK);
271 	imsk &= ~ioasic_devs[i].iad_intrbits;
272 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk);
273 
274 	ioasicintrs[dev].iai_func = ioasic_intrnull;
275 	ioasicintrs[dev].iai_arg = (void *)dev;
276 	evcount_detach(&ioasicintrs[dev].iai_count);
277 }
278 
279 int
280 ioasic_intrnull(val)
281 	void *val;
282 {
283 
284 	panic("ioasic_intrnull: uncaught IOASIC intr for cookie %ld",
285 	    (u_long)val);
286 }
287 
288 /*
289  * ASIC interrupt handler.
290  */
291 int
292 ioasic_intr(val)
293 	void *val;
294 {
295 	register struct ioasic_softc *sc = val;
296 	register int ifound;
297 	int gifound;
298 	u_int32_t sir, osir;
299 
300 	gifound = 0;
301 	do {
302 		ifound = 0;
303 		tc_syncbus();
304 
305 		osir = sir =
306 		    bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR);
307 
308 		/* XXX DUPLICATION OF INTERRUPT BIT INFORMATION... */
309 #define	CHECKINTR(slot, bits, clear)					\
310 		if (sir & (bits)) {					\
311 			ifound = 1;					\
312 			ioasicintrs[slot].iai_count.ec_count++;		\
313 			(*ioasicintrs[slot].iai_func)			\
314 			    (ioasicintrs[slot].iai_arg);		\
315 			if (clear)					\
316 				sir &= ~(bits);				\
317 		}
318 		CHECKINTR(IOASIC_DEV_SCC0, IOASIC_INTR_SCC_0, 0);
319 		CHECKINTR(IOASIC_DEV_SCC1, IOASIC_INTR_SCC_1, 0);
320 		CHECKINTR(IOASIC_DEV_LANCE, IOASIC_INTR_LANCE, 0);
321 		CHECKINTR(IOASIC_DEV_ISDN, IOASIC_INTR_ISDN_TXLOAD |
322 		    IOASIC_INTR_ISDN_RXLOAD | IOASIC_INTR_ISDN_OVRUN, 1);
323 
324 		if (sir != osir)
325 			bus_space_write_4(sc->sc_bst, sc->sc_bsh,
326 			    IOASIC_INTR, sir);
327 
328 		gifound |= ifound;
329 	} while (ifound);
330 
331 	return (gifound);
332 }
333 
334 /*
335  * Blink leds
336  */
337 
338 struct {
339 	int		patpos;
340 	struct timeout	tmo;
341 } led_blink_state;
342 
343 static const uint8_t led_pattern8[] = {
344 	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
345 	0x40, 0x20, 0x10, 0x08, 0x04, 0x02
346 };
347 
348 void
349 ioasic_led_blink(void *unused)
350 {
351 	extern int alpha_led_blink;
352 	vaddr_t rw_csr;
353 	u_int32_t pattern;
354 	int display_loadavg;
355 
356 	if (alpha_led_blink == 0) {
357 		pattern = 0;	/* all clear */
358 		led_blink_state.patpos = 0;
359 	} else {
360 #ifdef DEC_3000_300
361 		if (cputype == ST_DEC_3000_300)
362 			display_loadavg = 0;
363 		else
364 #endif
365 		switch (hwrpb->rpb_variation & SV_ST_MASK) {
366 		case SV_ST_FLAMINGO:
367 		case SV_ST_HOTPINK:
368 		case SV_ST_FLAMINGOPLUS:
369 		case SV_ST_ULTRA:
370 		case SV_ST_FLAMINGO45:
371 			/* 500/800/900, 2 7-segment display, display loadavg */
372 			display_loadavg = 1;
373 			break;
374 		case SV_ST_SANDPIPER:
375 		case SV_ST_SANDPLUS:
376 		case SV_ST_SANDPIPER45:
377 		default:
378 			/* 400/600/700, 8 leds, display moving pattern */
379 			display_loadavg = 0;
380 			break;
381 		}
382 
383 		if (display_loadavg)
384 			pattern = averunnable.ldavg[0] >> FSHIFT;
385 		else {
386 			pattern = led_pattern8[led_blink_state.patpos];
387 			led_blink_state.patpos =
388 			    (led_blink_state.patpos + 1) % sizeof(led_pattern8);
389 		}
390 	}
391 
392 	/*
393 	 * The low 8 bits, controlling the leds, are read-only in the
394 	 * CSR register, but read-write in its image at CSR + 4.
395 	 *
396 	 * On model 300, however, the internal 8 leds are at a different
397 	 * address, but the (better visible) power supply led is actually
398 	 * bit 5 in CSR (active low).
399 	 */
400 #ifdef DEC_3000_300
401 	if (cputype == ST_DEC_3000_300) {
402 		rw_csr = KV(0x1a0000000 + IOASIC_CSR + 4);
403 
404 		*(volatile uint32_t *)TC_3000_300_LED =
405 		    (*(volatile uint32_t *)TC_3000_300_LED & ~(0xff << 16)) |
406 		     (pattern << 16);
407 		/*
408 		 * Blink the power supply led 8x slower.  This relies
409 		 * on led_pattern8[] being a < 16 element array.
410 		 */
411 		*(volatile uint32_t *)rw_csr =
412 		    (*(volatile uint32_t *)rw_csr & ~(1 << 5)) ^
413 		    ((led_blink_state.patpos >> 3) << 5);
414 	} else
415 #endif
416 	{
417 		rw_csr = KV(0x1e0000000 + IOASIC_CSR + 4);
418 
419 		*(volatile uint32_t *)rw_csr =
420 		    (*(volatile uint32_t *)rw_csr & ~0xff) | pattern;
421 	}
422 
423 	if (alpha_led_blink != 0) {
424 		timeout_set(&led_blink_state.tmo, ioasic_led_blink, NULL);
425 		timeout_add(&led_blink_state.tmo,
426 		    (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 3)));
427 	}
428 }
429