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