xref: /netbsd-src/sys/arch/hppa/dev/lcd.c (revision d1579b2d70337e1b895f03478838f880e450f6da)
1*d1579b2dSriastradh /*	$NetBSD: lcd.c,v 1.2 2018/09/03 16:29:24 riastradh Exp $	*/
26d3ceb1dSskrll /*	OpenBSD: lcd.c,v 1.2 2007/07/20 22:13:45 kettenis Exp 	*/
36d3ceb1dSskrll 
46d3ceb1dSskrll /*
56d3ceb1dSskrll  * Copyright (c) 2007 Mark Kettenis
66d3ceb1dSskrll  *
76d3ceb1dSskrll  * Permission to use, copy, modify, and distribute this software for any
86d3ceb1dSskrll  * purpose with or without fee is hereby granted, provided that the above
96d3ceb1dSskrll  * copyright notice and this permission notice appear in all copies.
106d3ceb1dSskrll  *
116d3ceb1dSskrll  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
126d3ceb1dSskrll  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
136d3ceb1dSskrll  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
146d3ceb1dSskrll  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
156d3ceb1dSskrll  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
166d3ceb1dSskrll  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
176d3ceb1dSskrll  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
186d3ceb1dSskrll  */
196d3ceb1dSskrll 
206d3ceb1dSskrll #include <sys/param.h>
216d3ceb1dSskrll #include <sys/device.h>
226d3ceb1dSskrll #include <sys/kernel.h>
236d3ceb1dSskrll #include <sys/systm.h>
246d3ceb1dSskrll #include <sys/callout.h>
256d3ceb1dSskrll 
266d3ceb1dSskrll #include <machine/autoconf.h>
276d3ceb1dSskrll #include <sys/bus.h>
286d3ceb1dSskrll #include <machine/cpu.h>
296d3ceb1dSskrll #include <machine/pdc.h>
306d3ceb1dSskrll 
316d3ceb1dSskrll #define LCD_CLS		0x01
326d3ceb1dSskrll #define LCD_HOME	0x02
336d3ceb1dSskrll #define LCD_LOCATE(X, Y)	(((Y) & 1 ? 0xc0 : 0x80) | ((X) & 0x0f))
346d3ceb1dSskrll 
356d3ceb1dSskrll struct lcd_softc {
366d3ceb1dSskrll 	device_t		sc_dv;
376d3ceb1dSskrll 
386d3ceb1dSskrll 	bus_space_tag_t		sc_iot;
396d3ceb1dSskrll 	bus_space_handle_t 	sc_cmdh, sc_datah;
406d3ceb1dSskrll 
416d3ceb1dSskrll 	u_int			sc_delay;
426d3ceb1dSskrll 	uint8_t			sc_heartbeat[3];
436d3ceb1dSskrll 
446d3ceb1dSskrll 	struct callout		sc_to;
456d3ceb1dSskrll 	int			sc_on;
466d3ceb1dSskrll 	struct blink_lcd	sc_blink;
476d3ceb1dSskrll };
486d3ceb1dSskrll 
496d3ceb1dSskrll int	lcd_match(device_t, cfdata_t, void *);
506d3ceb1dSskrll void	lcd_attach(device_t, device_t, void *);
516d3ceb1dSskrll 
526d3ceb1dSskrll CFATTACH_DECL_NEW(lcd, sizeof(struct lcd_softc), lcd_match,
536d3ceb1dSskrll     lcd_attach, NULL, NULL);
546d3ceb1dSskrll 
556d3ceb1dSskrll void	lcd_write(struct lcd_softc *, const char *);
566d3ceb1dSskrll void	lcd_blink(void *, int);
576d3ceb1dSskrll void	lcd_blink_finish(void *);
586d3ceb1dSskrll 
596d3ceb1dSskrll int
lcd_match(device_t parent,cfdata_t match,void * aux)606d3ceb1dSskrll lcd_match(device_t parent, cfdata_t match, void *aux)
616d3ceb1dSskrll {
626d3ceb1dSskrll 	struct confargs *ca = aux;
636d3ceb1dSskrll 
646d3ceb1dSskrll 	if (strcmp(ca->ca_name, "lcd") == 0)
656d3ceb1dSskrll 		return 1;
666d3ceb1dSskrll 
676d3ceb1dSskrll 	return 0;
686d3ceb1dSskrll }
696d3ceb1dSskrll 
706d3ceb1dSskrll void
lcd_attach(device_t parent,device_t self,void * aux)716d3ceb1dSskrll lcd_attach(device_t parent, device_t self, void *aux)
726d3ceb1dSskrll {
736d3ceb1dSskrll 	struct lcd_softc *sc = device_private(self);
746d3ceb1dSskrll 	struct confargs *ca = aux;
756d3ceb1dSskrll 	struct pdc_chassis_lcd *pdc_lcd = &ca->ca_pcl;
766d3ceb1dSskrll 	int i;
776d3ceb1dSskrll 
786d3ceb1dSskrll 	sc->sc_dv = self;
796d3ceb1dSskrll 	sc->sc_iot = ca->ca_iot;
806d3ceb1dSskrll 
816d3ceb1dSskrll 	if (bus_space_map(sc->sc_iot, pdc_lcd->cmd_addr, 1, 0, &sc->sc_cmdh)) {
826d3ceb1dSskrll 		aprint_error(": can't map cmd register\n");
836d3ceb1dSskrll 		return;
846d3ceb1dSskrll 	}
856d3ceb1dSskrll 
866d3ceb1dSskrll 	if (bus_space_map(sc->sc_iot, pdc_lcd->data_addr, 1, 0,
876d3ceb1dSskrll 	    &sc->sc_datah)) {
886d3ceb1dSskrll 		aprint_error(": can't map data register\n");
896d3ceb1dSskrll 		bus_space_unmap(sc->sc_iot, sc->sc_cmdh, 1);
906d3ceb1dSskrll 		return;
916d3ceb1dSskrll 	}
926d3ceb1dSskrll 
936d3ceb1dSskrll 	aprint_normal(": model %d\n", pdc_lcd->model);
946d3ceb1dSskrll 
956d3ceb1dSskrll 	sc->sc_delay = pdc_lcd->delay;
966d3ceb1dSskrll 	for (i = 0; i < 3; i++)
976d3ceb1dSskrll 		sc->sc_heartbeat[i] = pdc_lcd->heartbeat[i];
986d3ceb1dSskrll 
996d3ceb1dSskrll 	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, LCD_CLS);
1006d3ceb1dSskrll 	delay(100 * sc->sc_delay);
1016d3ceb1dSskrll 
1026d3ceb1dSskrll 	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, LCD_LOCATE(0, 0));
1036d3ceb1dSskrll 	delay(sc->sc_delay);
1046d3ceb1dSskrll 	lcd_write(sc, "NetBSD/" MACHINE);
1056d3ceb1dSskrll 
1066d3ceb1dSskrll 	callout_init(&sc->sc_to, 0);
1076d3ceb1dSskrll 	callout_setfunc(&sc->sc_to, lcd_blink_finish, sc);
1086d3ceb1dSskrll 
1096d3ceb1dSskrll 	sc->sc_blink.bl_func = lcd_blink;
1106d3ceb1dSskrll 	sc->sc_blink.bl_arg = sc;
1116d3ceb1dSskrll 	blink_lcd_register(&sc->sc_blink);
1126d3ceb1dSskrll }
1136d3ceb1dSskrll 
1146d3ceb1dSskrll void
lcd_write(struct lcd_softc * sc,const char * str)1156d3ceb1dSskrll lcd_write(struct lcd_softc *sc, const char *str)
1166d3ceb1dSskrll {
1176d3ceb1dSskrll 	while (*str) {
1186d3ceb1dSskrll 		bus_space_write_1(sc->sc_iot, sc->sc_datah, 0, *str++);
1196d3ceb1dSskrll 		delay(sc->sc_delay);
1206d3ceb1dSskrll 	}
1216d3ceb1dSskrll }
1226d3ceb1dSskrll 
1236d3ceb1dSskrll void
lcd_blink(void * v,int on)1246d3ceb1dSskrll lcd_blink(void *v, int on)
1256d3ceb1dSskrll {
1266d3ceb1dSskrll 	struct lcd_softc *sc = v;
1276d3ceb1dSskrll 
1286d3ceb1dSskrll 	sc->sc_on = on;
1296d3ceb1dSskrll 	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, sc->sc_heartbeat[0]);
130*d1579b2dSriastradh 	callout_schedule(&sc->sc_to, uimax(1, (sc->sc_delay * hz) / 1000000));
1316d3ceb1dSskrll }
1326d3ceb1dSskrll 
1336d3ceb1dSskrll void
lcd_blink_finish(void * v)1346d3ceb1dSskrll lcd_blink_finish(void *v)
1356d3ceb1dSskrll {
1366d3ceb1dSskrll 	struct lcd_softc *sc = v;
1376d3ceb1dSskrll 	uint8_t data;
1386d3ceb1dSskrll 
1396d3ceb1dSskrll 	if (sc->sc_on)
1406d3ceb1dSskrll 		data = sc->sc_heartbeat[1];
1416d3ceb1dSskrll 	else
1426d3ceb1dSskrll 		data = sc->sc_heartbeat[2];
1436d3ceb1dSskrll 
1446d3ceb1dSskrll 	bus_space_write_1(sc->sc_iot, sc->sc_datah, 0, data);
1456d3ceb1dSskrll }
146