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