xref: /netbsd/sys/arch/hpcmips/vr/vrled.c (revision c4a72b64)
1 /*	$NetBSD: vrled.c,v 1.6 2002/10/02 05:26:56 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 SATO Kazumi. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/device.h>
31 #include <sys/reboot.h>
32 
33 #include <machine/bus.h>
34 #include <machine/config_hook.h>
35 
36 #include <hpcmips/vr/vripif.h>
37 #include <hpcmips/vr/vrledvar.h>
38 #include <hpcmips/vr/vrledreg.h>
39 
40 
41 #ifdef VRLEDDEBUG
42 #ifndef VRLEDDEBUG_CONF
43 #define VRLEDDEBUG_CONF 0
44 #endif /* VRLEDDEBUG_CONF */
45 int vrleddebug = VRLEDDEBUG_CONF;
46 #define DPRINTF(arg) if (vrleddebug) printf arg;
47 #define VPRINTF(arg) if (bootverbose||vrleddebug) printf arg;
48 #else /* VRLEDDEBUG */
49 #define DPRINTF(arg)
50 #define VPRINTF(arg) if (bootverbose) printf arg;
51 #endif /* VRLEDDEBUG */
52 
53 static int vrledmatch(struct device *, struct cfdata *, void *);
54 static void vrledattach(struct device *, struct device *, void *);
55 
56 static void vrled_write(struct vrled_softc *, int, unsigned short);
57 static unsigned short vrled_read(struct vrled_softc *, int);
58 
59 static void vrled_stop(struct vrled_softc *);
60 static void vrled_on(struct vrled_softc *);
61 static void vrled_blink(struct vrled_softc *);
62 static void vrled_flash(struct vrled_softc *);
63 static void vrled_change_state(struct vrled_softc *);
64 static int vrled_event(void *, int, long, void *);
65 
66 int vrled_intr(void *);
67 
68 CFATTACH_DECL(vrled, sizeof(struct vrled_softc),
69     vrledmatch, vrledattach, NULL, NULL);
70 
71 struct vrled_softc *this_led;
72 
73 static inline void
74 vrled_write(struct vrled_softc *sc, int port, unsigned short val)
75 {
76 
77 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
78 }
79 
80 static inline unsigned short
81 vrled_read(struct vrled_softc *sc, int port)
82 {
83 
84 	return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port));
85 }
86 
87 static int
88 vrledmatch(struct device *parent, struct cfdata *cf, void *aux)
89 {
90 
91 	return (1);
92 }
93 
94 static void
95 vrledattach(struct device *parent, struct device *self, void *aux)
96 {
97 	struct vrled_softc *sc = (struct vrled_softc *)self;
98 	struct vrip_attach_args *va = aux;
99 
100 	bus_space_tag_t iot = va->va_iot;
101 	bus_space_handle_t ioh;
102 
103 	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
104 		printf(": can't map bus space\n");
105 		return;
106 	}
107 
108 	sc->sc_iot = iot;
109 	sc->sc_ioh = ioh;
110 
111 	if (!(sc->sc_handler =
112 	    vrip_intr_establish(va->va_vc, va->va_unit, 0, IPL_TTY,
113 		vrled_intr, sc))) {
114 		printf (": can't map interrupt line.\n");
115 		return;
116 	}
117 
118 	printf("\n");
119 	/* clear interrupt status */
120 	vrled_write(sc, LEDINT_REG_W, LEDINT_ALL);
121 
122 	/* basic setup */
123 	sc->sc_state_cnt = 1;
124 	vrled_write(sc, LEDASTC_REG_W, 1); /* 1time */
125 	vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP);
126 	vrled_stop(sc);
127 
128 	sc->sc_hook = config_hook(CONFIG_HOOK_SET,
129 	    CONFIG_HOOK_LED, CONFIG_HOOK_SHARE, vrled_event, sc);
130 
131 	this_led = sc;
132 }
133 
134 
135 /*
136  * LED interrupt handler.
137  *
138  */
139 int
140 vrled_intr(void *arg)
141 {
142         struct vrled_softc *sc = arg;
143 	unsigned int intstat;
144 
145 	intstat = vrled_read(sc, LEDINT_REG_W);
146 	/* clear interrupt status */
147 	vrled_write(sc, LEDINT_REG_W, intstat);
148 	if (intstat&LEDINT_AUTOSTOP) {
149 		vrled_change_state(sc);
150 	}
151 	return (0);
152 }
153 
154 /*
155  * LED turn OFF
156  *
157  */
158 void
159 vrled_stop(struct vrled_softc *sc)
160 {
161 	vrled_write(sc, LEDHTS_REG_W, LEDHTS_DIV16SEC);
162 	vrled_write(sc, LEDLTS_REG_W, LEDLTS_4SEC);
163 	vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */
164 	vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP);
165 
166 	sc->sc_state = LEDOFF;
167 	sc->sc_next = LEDOFF;
168 }
169 
170 /*
171  * LED turn ON
172  *
173  */
174 void
175 vrled_on(struct vrled_softc *sc)
176 {
177 	vrled_write(sc, LEDHTS_REG_W, LEDHTS_SEC);
178 	vrled_write(sc, LEDLTS_REG_W, LEDLTS_DIV16SEC);
179 	vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */
180 	vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK);
181 
182 	sc->sc_state = LEDON;
183 	sc->sc_next = LEDON;
184 }
185 
186 /*
187  * LED blink
188  *
189  */
190 void
191 vrled_blink(struct vrled_softc *sc)
192 {
193 	int ledhts;
194 	int ledlts;
195 
196 	switch (sc->sc_next) {
197 	case LED1SB:
198 		ledhts = LEDHTS_DIV2SEC;
199 		ledlts = LEDLTS_DIV2SEC;
200 		break;
201 	case LED2SB:
202 		ledhts = LEDHTS_SEC;
203 		ledlts = LEDLTS_SEC;
204 		break;
205 	default:
206 		vrled_stop(sc);
207 		return;
208 	}
209 
210 	vrled_write(sc, LEDHTS_REG_W, ledhts);
211 	vrled_write(sc, LEDLTS_REG_W, ledlts);
212 	vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */
213 	vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP);
214 	vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK);
215 
216 	sc->sc_state = sc->sc_next;
217 }
218 
219 /*
220  * LED flash once
221  *
222  */
223 void
224 vrled_flash(struct vrled_softc *sc)
225 {
226 	int ledhts;
227 	int ledlts;
228 
229 	switch (sc->sc_next) {
230 	case LED8DIVF:
231 		ledhts = LEDHTS_DIV16SEC;
232 		ledlts = LEDLTS_DIV16SEC;
233 		break;
234 	case LED4DIVF:
235 		ledhts = LEDHTS_DIV8SEC;
236 		ledlts = LEDLTS_DIV8SEC;
237 		break;
238 	case LED2DIVF:
239 		ledhts = LEDHTS_DIV4SEC;
240 		ledlts = LEDLTS_DIV4SEC;
241 		break;
242 	case LED1SF:
243 		ledhts = LEDHTS_DIV2SEC;
244 		ledlts = LEDLTS_DIV2SEC;
245 		break;
246 	default:
247 		vrled_stop(sc);
248 		return;
249 	}
250 
251 	vrled_write(sc, LEDHTS_REG_W, ledhts);
252 	vrled_write(sc, LEDLTS_REG_W, ledlts);
253 	vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */
254 	vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK);
255 
256 	sc->sc_state = sc->sc_next;
257 	sc->sc_next = LEDOFF;
258 	sc->sc_state_cnt = 1;
259 }
260 
261 /*
262  * Change LED state
263  *
264  */
265 void
266 vrled_change_state(struct vrled_softc *sc)
267 {
268 
269 	switch (sc->sc_next) {
270 	case LEDOFF:
271 		vrled_stop(sc);
272 		break;
273 	case LEDON:
274 		vrled_on(sc);
275 		break;
276 	case LED1SB:
277 	case LED2SB:
278 		vrled_blink(sc);
279 		break;
280 	case LED8DIVF:
281 	case LED4DIVF:
282 	case LED2DIVF:
283 	case LED1SF:
284 		vrled_flash(sc);
285 		break;
286 	default:
287 		vrled_stop(sc);
288 		break;
289 	}
290 }
291 
292 /*
293  * Set LED state
294  *
295  */
296 void
297 vrled_set_state(struct vrled_softc *sc, vrled_status state)
298 {
299 
300 	int ledstate;
301 
302 	ledstate = vrled_read(sc, LEDCNT_REG_W);
303 	if (ledstate&LEDCNT_BLINK) { /* currently processing */
304 		if (sc->sc_next == state)
305 			sc->sc_state_cnt++;
306 		switch (sc->sc_next) {
307 		case LEDOFF:
308 		case LEDON:
309 			sc->sc_next = state;
310 			break;
311 		case LED8DIVF:
312 		case LED4DIVF:
313 		case LED2DIVF:
314 		case LED1SF:
315 			switch (state) {
316 			case LEDOFF:
317 			case LED8DIVF:
318 			case LED4DIVF:
319 			case LED2DIVF:
320 			case LED1SF:
321 				sc->sc_next = state;
322 				break;
323 			default:
324 				break;
325 			}
326 			break;
327 		case LED1SB:
328 		case LED2SB:
329 			switch (state) {
330 			case LEDOFF:
331 			case LEDON:
332 			case LED1SB:
333 			case LED2SB:
334 				sc->sc_next = state;
335 				break;
336 			default:
337 				break;
338 			}
339 			break;
340 		default:
341 			sc->sc_next = LEDOFF;
342 			break;
343 		}
344 		return;
345 	}
346 	sc->sc_next = state;
347 	vrled_change_state(sc);
348 }
349 
350 /*
351  * LED config hook events
352  *
353  */
354 int
355 vrled_event(void *ctx, int type, long id, void *msg)
356 {
357 	struct vrled_softc *sc = (struct vrled_softc *)ctx;
358         int why =*(int *)msg;
359 
360 	if (type != CONFIG_HOOK_SET
361 	    || id != CONFIG_HOOK_LED)
362 		return (1);
363 	if (msg == NULL)
364 		return (1);
365 
366         switch (why) {
367         case CONFIG_HOOK_LED_OFF:
368 		vrled_set_state(sc, LEDOFF);
369                 break;
370         case CONFIG_HOOK_LED_ON:
371 		vrled_set_state(sc, LEDON);
372                 break;
373         case CONFIG_HOOK_LED_FLASH:
374 		vrled_set_state(sc, LED8DIVF);
375                 break;
376         case CONFIG_HOOK_LED_FLASH2:
377 		vrled_set_state(sc, LED4DIVF);
378                 break;
379         case CONFIG_HOOK_LED_FLASH5:
380 		vrled_set_state(sc, LED2DIVF);
381                 break;
382         case CONFIG_HOOK_LED_BLINK:
383 		vrled_set_state(sc, LED1SB);
384                 break;
385         case CONFIG_HOOK_LED_BLINK2:
386 		vrled_set_state(sc, LED2SB);
387                 break;
388 	default:
389 		vrled_set_state(sc, LEDOFF);
390         }
391         return (0);
392 }
393 
394 /* end */
395