11.2Sriastrad/* $NetBSD: lcd.c,v 1.2 2018/09/03 16:29:24 riastradh 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.2Sriastrad callout_schedule(&sc->sc_to, uimax(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