xref: /openbsd/sys/arch/alpha/tc/ioasic.c (revision 09467b48)
1 /* $OpenBSD: ioasic.c,v 1.18 2017/10/11 08:14:28 mpi 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 void	ioasic_led_blink(void *);
95 
96 #define	C(x)	((void *)(u_long)(x))
97 #define	KV(x)	(ALPHA_PHYS_TO_K0SEG(x))
98 
99 #define	IOASIC_DEV_LANCE	0
100 #define	IOASIC_DEV_SCC0		1
101 #define	IOASIC_DEV_SCC1		2
102 #define	IOASIC_DEV_ISDN		3
103 
104 #define	IOASIC_DEV_BOGUS	-1
105 
106 #define	IOASIC_NCOOKIES		4
107 
108 struct ioasic_dev ioasic_devs[] = {
109 	{ "PMAD-BA ", IOASIC_SLOT_3_START, C(IOASIC_DEV_LANCE),
110 	  IOASIC_INTR_LANCE, },
111 	{ "z8530   ", IOASIC_SLOT_4_START, C(IOASIC_DEV_SCC0),
112 	  IOASIC_INTR_SCC_0, },
113 	{ "z8530   ", IOASIC_SLOT_6_START, C(IOASIC_DEV_SCC1),
114 	  IOASIC_INTR_SCC_1, },
115 	{ "TOY_RTC ", IOASIC_SLOT_8_START, C(IOASIC_DEV_BOGUS),
116 	  0, },
117 	{ "AMD79c30", IOASIC_SLOT_9_START, C(IOASIC_DEV_ISDN),
118 	  IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD,  },
119 };
120 int ioasic_ndevs = sizeof(ioasic_devs) / sizeof(ioasic_devs[0]);
121 
122 struct ioasicintr {
123 	int	(*iai_func)(void *);
124 	void	*iai_arg;
125 	struct evcount iai_count;
126 } ioasicintrs[IOASIC_NCOOKIES];
127 
128 tc_addr_t ioasic_base;		/* XXX XXX XXX */
129 
130 /* There can be only one. */
131 int ioasicfound;
132 
133 int
134 ioasicmatch(parent, cfdata, aux)
135 	struct device *parent;
136 	void *cfdata, *aux;
137 {
138 	struct tc_attach_args *ta = aux;
139 
140 	/* Make sure that we're looking for this type of device. */
141 	if (strncmp("FLAMG-IO", ta->ta_modname, TC_ROM_LLEN))
142 		return (0);
143 
144 	/* Check that it can actually exist. */
145 	if ((cputype != ST_DEC_3000_500) && (cputype != ST_DEC_3000_300))
146 		panic("ioasicmatch: how did we get here?");
147 
148 	if (ioasicfound)
149 		return (0);
150 
151 	return (1);
152 }
153 
154 void
155 ioasicattach(parent, self, aux)
156 	struct device *parent, *self;
157 	void *aux;
158 {
159 	struct ioasic_softc *sc = (struct ioasic_softc *)self;
160 	struct tc_attach_args *ta = aux;
161 #ifdef DEC_3000_300
162 	u_long ssr;
163 #endif
164 	u_long i, imsk;
165 
166 	ioasicfound = 1;
167 
168 	sc->sc_bst = ta->ta_memt;
169 	if (bus_space_map(ta->ta_memt, ta->ta_addr,
170 			0x400000, 0, &sc->sc_bsh)) {
171 		printf("%s: unable to map device\n", sc->sc_dv.dv_xname);
172 		return;
173 	}
174 	sc->sc_dmat = ta->ta_dmat;
175 
176 	ioasic_base = sc->sc_base = ta->ta_addr; /* XXX XXX XXX */
177 
178 #ifdef DEC_3000_300
179 	if (cputype == ST_DEC_3000_300) {
180 		ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
181 		ssr |= IOASIC_CSR_FASTMODE;
182 		bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
183 		printf(": slow mode\n");
184 	} else
185 #endif
186 		printf(": fast mode\n");
187 
188 	/*
189 	 * Turn off all device interrupt bits.
190 	 * (This does _not_ include 3000/300 TC option slot bits).
191 	 */
192 	imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK);
193 	for (i = 0; i < ioasic_ndevs; i++)
194 		imsk &= ~ioasic_devs[i].iad_intrbits;
195 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk);
196 
197 	/*
198 	 * Set up interrupt handlers.
199 	 */
200 	for (i = 0; i < IOASIC_NCOOKIES; i++) {
201 		ioasicintrs[i].iai_func = ioasic_intrnull;
202 		ioasicintrs[i].iai_arg = (void *)i;
203 	}
204 	tc_intr_establish(parent, ta->ta_cookie, IPL_NONE, ioasic_intr, sc,
205 	    NULL);
206 
207 	/*
208 	 * Try to configure each device.
209 	 */
210 	ioasic_attach_devs(sc, ioasic_devs, ioasic_ndevs);
211 
212 	ioasic_led_blink(NULL);
213 }
214 
215 void
216 ioasic_intr_establish(ioa, cookie, level, func, arg, name)
217 	struct device *ioa;
218 	void *cookie, *arg;
219 	int level;
220 	int (*func)(void *);
221 	const char *name;
222 {
223 	struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0];
224 	u_long dev, i, imsk;
225 
226 	dev = (u_long)cookie;
227 #ifdef DIAGNOSTIC
228 	/* XXX check cookie. */
229 #endif
230 
231 	if (ioasicintrs[dev].iai_func != ioasic_intrnull)
232 		panic("ioasic_intr_establish: cookie %lu twice", dev);
233 
234 	ioasicintrs[dev].iai_func = func;
235 	ioasicintrs[dev].iai_arg = arg;
236 	evcount_attach(&ioasicintrs[dev].iai_count, name, NULL);
237 
238 	/* Enable interrupts for the device. */
239 	for (i = 0; i < ioasic_ndevs; i++)
240 		if (ioasic_devs[i].iad_cookie == cookie)
241 			break;
242 	if (i == ioasic_ndevs)
243 		panic("ioasic_intr_establish: invalid cookie.");
244 
245 	imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK);
246         imsk |= ioasic_devs[i].iad_intrbits;
247         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk);
248 }
249 
250 void
251 ioasic_intr_disestablish(ioa, cookie)
252 	struct device *ioa;
253 	void *cookie;
254 {
255 	struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0];
256 	u_long dev, i, imsk;
257 
258 	dev = (u_long)cookie;
259 #ifdef DIAGNOSTIC
260 	/* XXX check cookie. */
261 #endif
262 
263 	if (ioasicintrs[dev].iai_func == ioasic_intrnull)
264 		panic("ioasic_intr_disestablish: cookie %lu missing intr", dev);
265 
266 	/* Enable interrupts for the device. */
267 	for (i = 0; i < ioasic_ndevs; i++)
268 		if (ioasic_devs[i].iad_cookie == cookie)
269 			break;
270 	if (i == ioasic_ndevs)
271 		panic("ioasic_intr_disestablish: invalid cookie.");
272 
273 	imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK);
274 	imsk &= ~ioasic_devs[i].iad_intrbits;
275 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk);
276 
277 	ioasicintrs[dev].iai_func = ioasic_intrnull;
278 	ioasicintrs[dev].iai_arg = (void *)dev;
279 	evcount_detach(&ioasicintrs[dev].iai_count);
280 }
281 
282 int
283 ioasic_intrnull(val)
284 	void *val;
285 {
286 
287 	panic("ioasic_intrnull: uncaught IOASIC intr for cookie %ld",
288 	    (u_long)val);
289 }
290 
291 /*
292  * ASIC interrupt handler.
293  */
294 int
295 ioasic_intr(val)
296 	void *val;
297 {
298 	register struct ioasic_softc *sc = val;
299 	register int ifound;
300 	int gifound;
301 	u_int32_t sir, osir;
302 
303 	gifound = 0;
304 	do {
305 		ifound = 0;
306 		tc_syncbus();
307 
308 		osir = sir =
309 		    bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR);
310 
311 		/* XXX DUPLICATION OF INTERRUPT BIT INFORMATION... */
312 #define	CHECKINTR(slot, bits, clear)					\
313 		if (sir & (bits)) {					\
314 			ifound = 1;					\
315 			ioasicintrs[slot].iai_count.ec_count++;		\
316 			(*ioasicintrs[slot].iai_func)			\
317 			    (ioasicintrs[slot].iai_arg);		\
318 			if (clear)					\
319 				sir &= ~(bits);				\
320 		}
321 		CHECKINTR(IOASIC_DEV_SCC0, IOASIC_INTR_SCC_0, 0);
322 		CHECKINTR(IOASIC_DEV_SCC1, IOASIC_INTR_SCC_1, 0);
323 		CHECKINTR(IOASIC_DEV_LANCE, IOASIC_INTR_LANCE, 0);
324 		CHECKINTR(IOASIC_DEV_ISDN, IOASIC_INTR_ISDN_TXLOAD |
325 		    IOASIC_INTR_ISDN_RXLOAD | IOASIC_INTR_ISDN_OVRUN, 1);
326 
327 		if (sir != osir)
328 			bus_space_write_4(sc->sc_bst, sc->sc_bsh,
329 			    IOASIC_INTR, sir);
330 
331 		gifound |= ifound;
332 	} while (ifound);
333 
334 	return (gifound);
335 }
336 
337 /*
338  * Blink leds
339  */
340 
341 struct {
342 	int		patpos;
343 	struct timeout	tmo;
344 } led_blink_state;
345 
346 static const uint8_t led_pattern8[] = {
347 	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
348 	0x40, 0x20, 0x10, 0x08, 0x04, 0x02
349 };
350 
351 void
352 ioasic_led_blink(void *unused)
353 {
354 	extern int alpha_led_blink;	/* machdep.c */
355 	vaddr_t rw_csr;
356 	u_int32_t pattern;
357 	int display_loadavg;
358 
359 	if (alpha_led_blink == 0) {
360 		pattern = 0;	/* all clear */
361 		led_blink_state.patpos = 0;
362 	} else {
363 #ifdef DEC_3000_300
364 		if (cputype == ST_DEC_3000_300)
365 			display_loadavg = 0;
366 		else
367 #endif
368 		switch (hwrpb->rpb_variation & SV_ST_MASK) {
369 		case SV_ST_FLAMINGO:
370 		case SV_ST_HOTPINK:
371 		case SV_ST_FLAMINGOPLUS:
372 		case SV_ST_ULTRA:
373 		case SV_ST_FLAMINGO45:
374 			/* 500/800/900, 2 7-segment display, display loadavg */
375 			display_loadavg = 1;
376 			break;
377 		case SV_ST_SANDPIPER:
378 		case SV_ST_SANDPLUS:
379 		case SV_ST_SANDPIPER45:
380 		default:
381 			/* 400/600/700, 8 leds, display moving pattern */
382 			display_loadavg = 0;
383 			break;
384 		}
385 
386 		if (display_loadavg)
387 			pattern = averunnable.ldavg[0] >> FSHIFT;
388 		else {
389 			pattern = led_pattern8[led_blink_state.patpos];
390 			led_blink_state.patpos =
391 			    (led_blink_state.patpos + 1) % sizeof(led_pattern8);
392 		}
393 	}
394 
395 	/*
396 	 * The low 8 bits, controlling the leds, are read-only in the
397 	 * CSR register, but read-write in its image at CSR + 4.
398 	 *
399 	 * On model 300, however, the internal 8 leds are at a different
400 	 * address, but the (better visible) power supply led is actually
401 	 * bit 5 in CSR (active low).
402 	 */
403 #ifdef DEC_3000_300
404 	if (cputype == ST_DEC_3000_300) {
405 		rw_csr = KV(0x1a0000000 + IOASIC_CSR + 4);
406 
407 		*(volatile uint32_t *)TC_3000_300_LED =
408 		    (*(volatile uint32_t *)TC_3000_300_LED & ~(0xff << 16)) |
409 		     (pattern << 16);
410 		/*
411 		 * Blink the power supply led 8x slower.  This relies
412 		 * on led_pattern8[] being a < 16 element array.
413 		 */
414 		*(volatile uint32_t *)rw_csr =
415 		    (*(volatile uint32_t *)rw_csr & ~(1 << 5)) ^
416 		    ((led_blink_state.patpos >> 3) << 5);
417 	} else
418 #endif
419 	{
420 		rw_csr = KV(0x1e0000000 + IOASIC_CSR + 4);
421 
422 		*(volatile uint32_t *)rw_csr =
423 		    (*(volatile uint32_t *)rw_csr & ~0xff) | pattern;
424 	}
425 
426 	if (alpha_led_blink != 0) {
427 		timeout_set(&led_blink_state.tmo, ioasic_led_blink, NULL);
428 		timeout_add(&led_blink_state.tmo,
429 		    (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 3)));
430 	}
431 }
432