lcd.c revision 1.1
11.1Sskrll/*	$NetBSD: lcd.c,v 1.1 2014/02/24 07:23:42 skrll Exp $	*/
21.1Sskrll/*	OpenBSD: lcd.c,v 1.2 2007/07/20 22:13:45 kettenis Exp 	*/
31.1Sskrll
41.1Sskrll/*
51.1Sskrll * Copyright (c) 2007 Mark Kettenis
61.1Sskrll *
71.1Sskrll * Permission to use, copy, modify, and distribute this software for any
81.1Sskrll * purpose with or without fee is hereby granted, provided that the above
91.1Sskrll * copyright notice and this permission notice appear in all copies.
101.1Sskrll *
111.1Sskrll * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
121.1Sskrll * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
131.1Sskrll * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
141.1Sskrll * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
151.1Sskrll * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
161.1Sskrll * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
171.1Sskrll * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
181.1Sskrll */
191.1Sskrll
201.1Sskrll#include <sys/param.h>
211.1Sskrll#include <sys/device.h>
221.1Sskrll#include <sys/kernel.h>
231.1Sskrll#include <sys/systm.h>
241.1Sskrll#include <sys/callout.h>
251.1Sskrll
261.1Sskrll#include <machine/autoconf.h>
271.1Sskrll#include <sys/bus.h>
281.1Sskrll#include <machine/cpu.h>
291.1Sskrll#include <machine/pdc.h>
301.1Sskrll
311.1Sskrll#define LCD_CLS		0x01
321.1Sskrll#define LCD_HOME	0x02
331.1Sskrll#define LCD_LOCATE(X, Y)	(((Y) & 1 ? 0xc0 : 0x80) | ((X) & 0x0f))
341.1Sskrll
351.1Sskrllstruct lcd_softc {
361.1Sskrll	device_t		sc_dv;
371.1Sskrll
381.1Sskrll	bus_space_tag_t		sc_iot;
391.1Sskrll	bus_space_handle_t 	sc_cmdh, sc_datah;
401.1Sskrll
411.1Sskrll	u_int			sc_delay;
421.1Sskrll	uint8_t			sc_heartbeat[3];
431.1Sskrll
441.1Sskrll	struct callout		sc_to;
451.1Sskrll	int			sc_on;
461.1Sskrll	struct blink_lcd	sc_blink;
471.1Sskrll};
481.1Sskrll
491.1Sskrllint	lcd_match(device_t, cfdata_t, void *);
501.1Sskrllvoid	lcd_attach(device_t, device_t, void *);
511.1Sskrll
521.1SskrllCFATTACH_DECL_NEW(lcd, sizeof(struct lcd_softc), lcd_match,
531.1Sskrll    lcd_attach, NULL, NULL);
541.1Sskrll
551.1Sskrllvoid	lcd_write(struct lcd_softc *, const char *);
561.1Sskrllvoid	lcd_blink(void *, int);
571.1Sskrllvoid	lcd_blink_finish(void *);
581.1Sskrll
591.1Sskrllint
601.1Sskrlllcd_match(device_t parent, cfdata_t match, void *aux)
611.1Sskrll{
621.1Sskrll	struct confargs *ca = aux;
631.1Sskrll
641.1Sskrll	if (strcmp(ca->ca_name, "lcd") == 0)
651.1Sskrll		return 1;
661.1Sskrll
671.1Sskrll	return 0;
681.1Sskrll}
691.1Sskrll
701.1Sskrllvoid
711.1Sskrlllcd_attach(device_t parent, device_t self, void *aux)
721.1Sskrll{
731.1Sskrll	struct lcd_softc *sc = device_private(self);
741.1Sskrll	struct confargs *ca = aux;
751.1Sskrll	struct pdc_chassis_lcd *pdc_lcd = &ca->ca_pcl;
761.1Sskrll	int i;
771.1Sskrll
781.1Sskrll	sc->sc_dv = self;
791.1Sskrll	sc->sc_iot = ca->ca_iot;
801.1Sskrll
811.1Sskrll	if (bus_space_map(sc->sc_iot, pdc_lcd->cmd_addr, 1, 0, &sc->sc_cmdh)) {
821.1Sskrll		aprint_error(": can't map cmd register\n");
831.1Sskrll		return;
841.1Sskrll	}
851.1Sskrll
861.1Sskrll	if (bus_space_map(sc->sc_iot, pdc_lcd->data_addr, 1, 0,
871.1Sskrll	    &sc->sc_datah)) {
881.1Sskrll		aprint_error(": can't map data register\n");
891.1Sskrll		bus_space_unmap(sc->sc_iot, sc->sc_cmdh, 1);
901.1Sskrll		return;
911.1Sskrll	}
921.1Sskrll
931.1Sskrll	aprint_normal(": model %d\n", pdc_lcd->model);
941.1Sskrll
951.1Sskrll	sc->sc_delay = pdc_lcd->delay;
961.1Sskrll	for (i = 0; i < 3; i++)
971.1Sskrll		sc->sc_heartbeat[i] = pdc_lcd->heartbeat[i];
981.1Sskrll
991.1Sskrll	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, LCD_CLS);
1001.1Sskrll	delay(100 * sc->sc_delay);
1011.1Sskrll
1021.1Sskrll	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, LCD_LOCATE(0, 0));
1031.1Sskrll	delay(sc->sc_delay);
1041.1Sskrll	lcd_write(sc, "NetBSD/" MACHINE);
1051.1Sskrll
1061.1Sskrll	callout_init(&sc->sc_to, 0);
1071.1Sskrll	callout_setfunc(&sc->sc_to, lcd_blink_finish, sc);
1081.1Sskrll
1091.1Sskrll	sc->sc_blink.bl_func = lcd_blink;
1101.1Sskrll	sc->sc_blink.bl_arg = sc;
1111.1Sskrll	blink_lcd_register(&sc->sc_blink);
1121.1Sskrll}
1131.1Sskrll
1141.1Sskrllvoid
1151.1Sskrlllcd_write(struct lcd_softc *sc, const char *str)
1161.1Sskrll{
1171.1Sskrll	while (*str) {
1181.1Sskrll		bus_space_write_1(sc->sc_iot, sc->sc_datah, 0, *str++);
1191.1Sskrll		delay(sc->sc_delay);
1201.1Sskrll	}
1211.1Sskrll}
1221.1Sskrll
1231.1Sskrllvoid
1241.1Sskrlllcd_blink(void *v, int on)
1251.1Sskrll{
1261.1Sskrll	struct lcd_softc *sc = v;
1271.1Sskrll
1281.1Sskrll	sc->sc_on = on;
1291.1Sskrll	bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, sc->sc_heartbeat[0]);
1301.1Sskrll	callout_schedule(&sc->sc_to, max(1, (sc->sc_delay * hz) / 1000000));
1311.1Sskrll}
1321.1Sskrll
1331.1Sskrllvoid
1341.1Sskrlllcd_blink_finish(void *v)
1351.1Sskrll{
1361.1Sskrll	struct lcd_softc *sc = v;
1371.1Sskrll	uint8_t data;
1381.1Sskrll
1391.1Sskrll	if (sc->sc_on)
1401.1Sskrll		data = sc->sc_heartbeat[1];
1411.1Sskrll	else
1421.1Sskrll		data = sc->sc_heartbeat[2];
1431.1Sskrll
1441.1Sskrll	bus_space_write_1(sc->sc_iot, sc->sc_datah, 0, data);
1451.1Sskrll}
146