xref: /openbsd-src/sys/arch/hppa/dev/lcd.c (revision 78d5ff0ec949396ff3bbc97f51b741a17179ba18)
1*78d5ff0eSmpi /*	$OpenBSD: lcd.c,v 1.6 2022/03/13 08:04:38 mpi Exp $	*/
2b87e57a8Skettenis 
3b87e57a8Skettenis /*
4b87e57a8Skettenis  * Copyright (c) 2007 Mark Kettenis
5b87e57a8Skettenis  *
6b87e57a8Skettenis  * Permission to use, copy, modify, and distribute this software for any
7b87e57a8Skettenis  * purpose with or without fee is hereby granted, provided that the above
8b87e57a8Skettenis  * copyright notice and this permission notice appear in all copies.
9b87e57a8Skettenis  *
10b87e57a8Skettenis  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11b87e57a8Skettenis  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12b87e57a8Skettenis  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13b87e57a8Skettenis  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14b87e57a8Skettenis  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15b87e57a8Skettenis  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16b87e57a8Skettenis  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17b87e57a8Skettenis  */
18b87e57a8Skettenis 
19b87e57a8Skettenis #include <sys/param.h>
20b87e57a8Skettenis #include <sys/device.h>
21b87e57a8Skettenis #include <sys/kernel.h>
22b87e57a8Skettenis #include <sys/systm.h>
23f6908264Skettenis #include <sys/timeout.h>
24b87e57a8Skettenis 
25b87e57a8Skettenis #include <machine/autoconf.h>
26b87e57a8Skettenis #include <machine/bus.h>
27f6908264Skettenis #include <machine/cpu.h>
28b87e57a8Skettenis #include <machine/pdc.h>
29b87e57a8Skettenis 
30b87e57a8Skettenis #define LCD_CLS		0x01
31b87e57a8Skettenis #define LCD_HOME	0x02
32b87e57a8Skettenis #define LCD_LOCATE(X, Y)	(((Y) & 1 ? 0xc0 : 0x80) | ((X) & 0x0f))
33b87e57a8Skettenis 
34b87e57a8Skettenis struct lcd_softc {
35f6908264Skettenis 	struct device		sc_dv;
36b87e57a8Skettenis 
37b87e57a8Skettenis 	bus_space_tag_t		sc_iot;
38b87e57a8Skettenis 	bus_space_handle_t 	sc_cmdh, sc_datah;
39b87e57a8Skettenis 
40b87e57a8Skettenis 	u_int			sc_delay;
41f6908264Skettenis 	u_int8_t		sc_heartbeat[3];
42f6908264Skettenis 
43f6908264Skettenis 	struct timeout		sc_to;
44f6908264Skettenis 	int			sc_on;
45f6908264Skettenis 	struct blink_led	sc_blink;
46b87e57a8Skettenis };
47b87e57a8Skettenis 
48b87e57a8Skettenis int	lcd_match(struct device *, void *, void *);
49b87e57a8Skettenis void	lcd_attach(struct device *, struct device *, void *);
50b87e57a8Skettenis 
51*78d5ff0eSmpi const struct cfattach lcd_ca = {
52b87e57a8Skettenis 	sizeof(struct lcd_softc), lcd_match, lcd_attach
53b87e57a8Skettenis };
54b87e57a8Skettenis 
55b87e57a8Skettenis struct cfdriver lcd_cd = {
56b87e57a8Skettenis 	NULL, "lcd", DV_DULL
57b87e57a8Skettenis };
58b87e57a8Skettenis 
59ef89f9e6Smpi void	lcd_mountroot(struct device *);
60b87e57a8Skettenis void	lcd_write(struct lcd_softc *, const char *);
61f6908264Skettenis void	lcd_blink(void *, int);
62f6908264Skettenis void	lcd_blink_finish(void *);
63b87e57a8Skettenis 
64b87e57a8Skettenis int
lcd_match(struct device * parent,void * match,void * aux)65b87e57a8Skettenis lcd_match(struct device *parent, void *match, void *aux)
66b87e57a8Skettenis {
67b87e57a8Skettenis 	struct confargs *ca = aux;
68b87e57a8Skettenis 
69b87e57a8Skettenis 	if (strcmp(ca->ca_name, "lcd") == 0)
70b87e57a8Skettenis 		return (1);
71b87e57a8Skettenis 
72b87e57a8Skettenis 	return (0);
73b87e57a8Skettenis }
74b87e57a8Skettenis 
75b87e57a8Skettenis void
lcd_attach(struct device * parent,struct device * self,void * aux)76b87e57a8Skettenis lcd_attach(struct device *parent, struct device *self, void *aux)
77b87e57a8Skettenis {
78b87e57a8Skettenis 	struct lcd_softc *sc = (struct lcd_softc *)self;
79b87e57a8Skettenis 	struct confargs *ca = aux;
80b87e57a8Skettenis 	struct pdc_chassis_lcd *pdc_lcd = (void *)ca->ca_pdc_iodc_read;
81f6908264Skettenis 	int i;
82b87e57a8Skettenis 
83b87e57a8Skettenis 	sc->sc_iot = ca->ca_iot;
84b87e57a8Skettenis 	if (bus_space_map(sc->sc_iot, pdc_lcd->cmd_addr,
85b87e57a8Skettenis 		1, 0, &sc->sc_cmdh)) {
86b87e57a8Skettenis 		printf(": cannot map cmd register\n");
87b87e57a8Skettenis 		return;
88b87e57a8Skettenis 	}
89b87e57a8Skettenis 
90b87e57a8Skettenis 	if (bus_space_map(sc->sc_iot, pdc_lcd->data_addr,
91b87e57a8Skettenis 		1, 0, &sc->sc_datah)) {
92b87e57a8Skettenis 		printf(": cannot map data register\n");
93b87e57a8Skettenis 		bus_space_unmap(sc->sc_iot, sc->sc_cmdh, 1);
94b87e57a8Skettenis 		return;
95b87e57a8Skettenis 	}
96b87e57a8Skettenis 
97f6908264Skettenis 	printf(": model %d\n", pdc_lcd->model);
98f6908264Skettenis 
99b87e57a8Skettenis 	sc->sc_delay = pdc_lcd->delay;
100f6908264Skettenis 	for (i = 0; i < 3; i++)
101f6908264Skettenis 		sc->sc_heartbeat[i] = pdc_lcd->heartbeat[i];
102b87e57a8Skettenis 
1032038bf0aSjsing 	timeout_set(&sc->sc_to, lcd_blink_finish, sc);
1042038bf0aSjsing 
1052038bf0aSjsing 	sc->sc_blink.bl_func = lcd_blink;
1062038bf0aSjsing 	sc->sc_blink.bl_arg = sc;
1072038bf0aSjsing 	blink_led_register(&sc->sc_blink);
1082038bf0aSjsing 
109ef89f9e6Smpi 	config_mountroot(self, lcd_mountroot);
1102038bf0aSjsing }
1112038bf0aSjsing 
1122038bf0aSjsing void
lcd_mountroot(struct device * self)113ef89f9e6Smpi lcd_mountroot(struct device *self)
1142038bf0aSjsing {
115ef89f9e6Smpi 	struct lcd_softc *sc = (struct lcd_softc *)self;
1162038bf0aSjsing 
117b87e57a8Skettenis 	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, LCD_CLS);
118b87e57a8Skettenis 	delay(100 * sc->sc_delay);
119b87e57a8Skettenis 
120b87e57a8Skettenis 	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, LCD_LOCATE(0, 0));
121b87e57a8Skettenis 	delay(sc->sc_delay);
122b87e57a8Skettenis 	lcd_write(sc, "OpenBSD/" MACHINE);
123b87e57a8Skettenis }
124b87e57a8Skettenis 
125b87e57a8Skettenis void
lcd_write(struct lcd_softc * sc,const char * str)126b87e57a8Skettenis lcd_write(struct lcd_softc *sc, const char *str)
127b87e57a8Skettenis {
128b87e57a8Skettenis 	while (*str) {
129b87e57a8Skettenis 		bus_space_write_1(sc->sc_iot, sc->sc_datah, 0, *str++);
130b87e57a8Skettenis 		delay(sc->sc_delay);
131b87e57a8Skettenis 	}
132b87e57a8Skettenis }
133f6908264Skettenis 
134f6908264Skettenis void
lcd_blink(void * v,int on)135f6908264Skettenis lcd_blink(void *v, int on)
136f6908264Skettenis {
137f6908264Skettenis 	struct lcd_softc *sc = v;
138f6908264Skettenis 
139f6908264Skettenis 	sc->sc_on = on;
140f6908264Skettenis 	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, sc->sc_heartbeat[0]);
141b895fb73Scheloha 	timeout_add_usec(&sc->sc_to, sc->sc_delay);
142f6908264Skettenis }
143f6908264Skettenis 
144f6908264Skettenis void
lcd_blink_finish(void * v)145f6908264Skettenis lcd_blink_finish(void *v)
146f6908264Skettenis {
147f6908264Skettenis 	struct lcd_softc *sc = v;
148f6908264Skettenis 	u_int8_t data;
149f6908264Skettenis 
150f6908264Skettenis 	if (sc->sc_on)
151f6908264Skettenis 		data = sc->sc_heartbeat[1];
152f6908264Skettenis 	else
153f6908264Skettenis 		data = sc->sc_heartbeat[2];
154f6908264Skettenis 
155f6908264Skettenis 	bus_space_write_1(sc->sc_iot, sc->sc_datah, 0, data);
156f6908264Skettenis }
157