xref: /netbsd-src/sys/arch/hpcmips/dev/teliosio.c (revision cbab9cadce21ae72fac13910001079fff214cc29)
1*cbab9cadSchs /*	$NetBSD: teliosio.c,v 1.4 2012/10/27 17:17:53 chs Exp $	*/
229110789Snakayama 
329110789Snakayama /*
429110789Snakayama  * Copyright (c) 2005 Takeshi Nakayama.
529110789Snakayama  * All rights reserved.
629110789Snakayama  *
729110789Snakayama  * Redistribution and use in source and binary forms, with or without
829110789Snakayama  * modification, are permitted provided that the following conditions
929110789Snakayama  * are met:
1029110789Snakayama  * 1. Redistributions of source code must retain the above copyright
1129110789Snakayama  *    notice, this list of conditions and the following disclaimer.
1229110789Snakayama  * 2. Redistributions in binary form must reproduce the above copyright
1329110789Snakayama  *    notice, this list of conditions and the following disclaimer in the
1429110789Snakayama  *    documentation and/or other materials provided with the distribution.
1529110789Snakayama  *
1629110789Snakayama  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1729110789Snakayama  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1829110789Snakayama  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1929110789Snakayama  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2029110789Snakayama  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2129110789Snakayama  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2229110789Snakayama  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2329110789Snakayama  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2429110789Snakayama  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2529110789Snakayama  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2629110789Snakayama  */
2729110789Snakayama 
2829110789Snakayama /*
2929110789Snakayama  * Sharp Telios machine dependent I/O (LCD backlight/Battery unit) driver
3029110789Snakayama  */
3129110789Snakayama 
3229110789Snakayama #include <sys/cdefs.h>
33*cbab9cadSchs __KERNEL_RCSID(0, "$NetBSD: teliosio.c,v 1.4 2012/10/27 17:17:53 chs Exp $");
3429110789Snakayama 
3529110789Snakayama #include "apmdev.h"
3629110789Snakayama 
3729110789Snakayama #include <sys/param.h>
3829110789Snakayama #include <sys/systm.h>
3929110789Snakayama #include <sys/device.h>
4029110789Snakayama 
4129110789Snakayama #include <machine/bus.h>
4229110789Snakayama #include <machine/config_hook.h>
4329110789Snakayama 
4429110789Snakayama #include <hpcmips/tx/tx39var.h>
4529110789Snakayama #include <hpcmips/tx/txcsbusvar.h>
4629110789Snakayama 
4729110789Snakayama #if NAPMDEV > 0
4829110789Snakayama #include <dev/apm/apmbios.h>
4929110789Snakayama #define __TX39IO_PRIVATE
5029110789Snakayama #include <hpcmips/tx/tx39ioreg.h>
5129110789Snakayama #include <hpcmips/tx/tx39timerreg.h>
5229110789Snakayama #endif
5329110789Snakayama 
5429110789Snakayama #include <hpcmips/dev/teliosioreg.h>
5529110789Snakayama 
5629110789Snakayama struct teliosio_softc {
5729110789Snakayama 	tx_chipset_tag_t sc_tc;
5829110789Snakayama 	bus_space_tag_t sc_regt;
5929110789Snakayama 	bus_space_handle_t sc_regh;
6029110789Snakayama 
6129110789Snakayama 	int sc_backlight;
6229110789Snakayama 	int sc_brightness;
6329110789Snakayama #define MAX_BRIGHTNESS 9
6429110789Snakayama #define BRIGHTNESSVAL(n) \
6529110789Snakayama 	((n) <= 0 ? 0 : ((n) <= MAX_BRIGHTNESS ? (n) : MAX_BRIGHTNESS) * 9 - 1)
6629110789Snakayama };
6729110789Snakayama 
68*cbab9cadSchs static int teliosio_match(device_t, cfdata_t, void *);
69*cbab9cadSchs static void teliosio_attach(device_t, device_t, void *);
7029110789Snakayama static int teliosio_event(void *, int, long, void *);
7129110789Snakayama 
7229110789Snakayama /* LCD backlight control */
7329110789Snakayama static void teliosio_backlight(struct teliosio_softc *, int);
7429110789Snakayama static void teliosio_brightness(struct teliosio_softc *, int);
7529110789Snakayama 
7629110789Snakayama /* Battery unit control */
7729110789Snakayama #if NAPMDEV > 0
7829110789Snakayama static int teliosio_ac_state(struct teliosio_softc *);
7929110789Snakayama static int teliosio_mbu_state(struct teliosio_softc *);
8029110789Snakayama static void teliosio_mbu_write(tx_chipset_tag_t, int);
8129110789Snakayama static int teliosio_mbu_read(tx_chipset_tag_t);
8229110789Snakayama #endif
8329110789Snakayama 
84*cbab9cadSchs CFATTACH_DECL_NEW(teliosio, sizeof(struct teliosio_softc),
8529110789Snakayama 	      teliosio_match, teliosio_attach, NULL, NULL);
8629110789Snakayama 
8729110789Snakayama static int
teliosio_match(device_t parent,cfdata_t cf,void * aux)88*cbab9cadSchs teliosio_match(device_t parent, cfdata_t cf, void *aux)
8929110789Snakayama {
9029110789Snakayama 
9129110789Snakayama 	return 2;	/* attach before plumvideo */
9229110789Snakayama }
9329110789Snakayama 
9429110789Snakayama static void
teliosio_attach(device_t parent,device_t self,void * aux)95*cbab9cadSchs teliosio_attach(device_t parent, device_t self, void *aux)
9629110789Snakayama {
9729110789Snakayama 	struct cs_attach_args *ca = aux;
98*cbab9cadSchs 	struct teliosio_softc *sc = device_private(self);
9929110789Snakayama 
10029110789Snakayama 	sc->sc_tc = ca->ca_tc;
10129110789Snakayama 	sc->sc_regt = ca->ca_csreg.cstag;
10229110789Snakayama 
10329110789Snakayama 	if (bus_space_map(sc->sc_regt, TELIOSIO_REGBASE, TELIOSIO_REGSIZE,
10429110789Snakayama 			  0, &sc->sc_regh)) {
10529110789Snakayama 		printf(": register map failed\n");
10629110789Snakayama 		return;
10729110789Snakayama 	}
10829110789Snakayama 	printf("\n");
10929110789Snakayama 
11029110789Snakayama 	sc->sc_backlight = 1;
11129110789Snakayama 	sc->sc_brightness = MAX_BRIGHTNESS;
11229110789Snakayama 
11329110789Snakayama 	config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_POWER_LCDLIGHT,
11429110789Snakayama 		    CONFIG_HOOK_SHARE, teliosio_event, sc);
11529110789Snakayama 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_POWER_LCDLIGHT,
11629110789Snakayama 		    CONFIG_HOOK_SHARE, teliosio_event, sc);
11729110789Snakayama 	config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS,
11829110789Snakayama 		    CONFIG_HOOK_SHARE, teliosio_event, sc);
11929110789Snakayama 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS,
12029110789Snakayama 		    CONFIG_HOOK_SHARE, teliosio_event, sc);
12129110789Snakayama 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX,
12229110789Snakayama 		    CONFIG_HOOK_SHARE, teliosio_event, sc);
12329110789Snakayama #if NAPMDEV > 0
12429110789Snakayama 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_ACADAPTER,
12529110789Snakayama 		    CONFIG_HOOK_SHARE, teliosio_event, sc);
12629110789Snakayama 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BATTERYVAL,
12729110789Snakayama 		    CONFIG_HOOK_SHARE, teliosio_event, sc);
12829110789Snakayama #endif
12929110789Snakayama }
13029110789Snakayama 
13129110789Snakayama static int
teliosio_event(void * ctx,int type,long id,void * msg)13229110789Snakayama teliosio_event(void *ctx, int type, long id, void *msg)
13329110789Snakayama {
13429110789Snakayama 	struct teliosio_softc *sc = ctx;
13529110789Snakayama 
13629110789Snakayama 	switch (type) {
13729110789Snakayama 	case CONFIG_HOOK_SET:
13829110789Snakayama 		switch (id) {
13929110789Snakayama 		case CONFIG_HOOK_POWER_LCDLIGHT:
14029110789Snakayama 			teliosio_backlight(sc, (int)msg);
14129110789Snakayama 			break;
14229110789Snakayama 		case CONFIG_HOOK_BRIGHTNESS:
14329110789Snakayama 			teliosio_brightness(sc, *(int *)msg + 1);
14429110789Snakayama 			break;
14529110789Snakayama 		default:
14629110789Snakayama 			return 1;
14729110789Snakayama 		}
14829110789Snakayama 		break;
14929110789Snakayama 	case CONFIG_HOOK_GET:
15029110789Snakayama 		switch (id) {
15129110789Snakayama 		case CONFIG_HOOK_POWER_LCDLIGHT:
15229110789Snakayama 			*(int *)msg = sc->sc_backlight;
15329110789Snakayama 			break;
15429110789Snakayama 		case CONFIG_HOOK_BRIGHTNESS:
15529110789Snakayama 			*(int *)msg = sc->sc_brightness - 1;
15629110789Snakayama 			break;
15729110789Snakayama 		case CONFIG_HOOK_BRIGHTNESS_MAX:
15829110789Snakayama 			*(int *)msg = MAX_BRIGHTNESS - 1;
15929110789Snakayama 			break;
16029110789Snakayama #if NAPMDEV > 0
16129110789Snakayama 		case CONFIG_HOOK_ACADAPTER:
16229110789Snakayama 			*(int *)msg = teliosio_ac_state(sc);
16329110789Snakayama 			break;
16429110789Snakayama 		case CONFIG_HOOK_BATTERYVAL:
16529110789Snakayama 			*(int *)msg = teliosio_mbu_state(sc) / 2;
16629110789Snakayama 			break;
16729110789Snakayama #endif
16829110789Snakayama 		default:
16929110789Snakayama 			return 1;
17029110789Snakayama 		}
17129110789Snakayama 		break;
17229110789Snakayama 	default:
17329110789Snakayama 		return 1;
17429110789Snakayama 	}
17529110789Snakayama 
17629110789Snakayama 	return 0;
17729110789Snakayama }
17829110789Snakayama 
17929110789Snakayama /*
18029110789Snakayama  * LCD backlight control
18129110789Snakayama  */
18229110789Snakayama static void
teliosio_backlight(struct teliosio_softc * sc,int on)18329110789Snakayama teliosio_backlight(struct teliosio_softc *sc, int on)
18429110789Snakayama {
18529110789Snakayama 	int brightness;
18629110789Snakayama 
18729110789Snakayama 	sc->sc_backlight = on;
18829110789Snakayama 	if (on) {
18929110789Snakayama 		teliosio_brightness(sc, sc->sc_brightness);
19029110789Snakayama 	} else {
19129110789Snakayama 		brightness = sc->sc_brightness;
19229110789Snakayama 		teliosio_brightness(sc, 0);
19329110789Snakayama 		sc->sc_brightness = brightness;
19429110789Snakayama 	}
19529110789Snakayama }
19629110789Snakayama 
19729110789Snakayama static void
teliosio_brightness(struct teliosio_softc * sc,int val)19829110789Snakayama teliosio_brightness(struct teliosio_softc *sc, int val)
19929110789Snakayama {
20029110789Snakayama 	bus_space_tag_t regt = sc->sc_regt;
20129110789Snakayama 	bus_space_handle_t regh = sc->sc_regh;
20229110789Snakayama 	u_int16_t period;
20329110789Snakayama 
20429110789Snakayama 	if (val < 0)
20529110789Snakayama 		val = 0;
20629110789Snakayama 	else if (val > MAX_BRIGHTNESS)
20729110789Snakayama 		val = MAX_BRIGHTNESS;
20829110789Snakayama 	sc->sc_brightness = val;
20929110789Snakayama 
21029110789Snakayama 	period = bus_space_read_2(regt, regh, TELIOSIO_BACKLIGHT_PERIOD);
21129110789Snakayama 	if (val)
21229110789Snakayama 		period |= TELIOSIO_BACKLIGHT_PERIOD_EN;
21329110789Snakayama 	else
21429110789Snakayama 		period &= ~TELIOSIO_BACKLIGHT_PERIOD_EN;
21529110789Snakayama 	bus_space_write_2(regt, regh, TELIOSIO_BACKLIGHT_PERIOD, period);
21629110789Snakayama 	bus_space_write_2(regt, regh, TELIOSIO_BACKLIGHT_RESET,
21729110789Snakayama 			  BRIGHTNESSVAL(val));
21829110789Snakayama }
21929110789Snakayama 
22029110789Snakayama /*
22129110789Snakayama  * Battery unit control
22229110789Snakayama  */
22329110789Snakayama #if NAPMDEV > 0
22429110789Snakayama static int
teliosio_ac_state(struct teliosio_softc * sc)22529110789Snakayama teliosio_ac_state(struct teliosio_softc *sc)
22629110789Snakayama {
22729110789Snakayama 	tx_chipset_tag_t tc = sc->sc_tc;
22829110789Snakayama 	txreg_t reg;
22929110789Snakayama 
23029110789Snakayama 	reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG);
23129110789Snakayama 	return (reg & TELIOSIO_AC_STATE) ? APM_AC_OFF : APM_AC_ON;
23229110789Snakayama }
23329110789Snakayama 
23429110789Snakayama static int
teliosio_mbu_state(struct teliosio_softc * sc)23529110789Snakayama teliosio_mbu_state(struct teliosio_softc *sc)
23629110789Snakayama {
23729110789Snakayama 	tx_chipset_tag_t tc = sc->sc_tc;
23829110789Snakayama 	int val;
23929110789Snakayama 
24029110789Snakayama 	teliosio_mbu_write(tc, 0x00);
24129110789Snakayama 	delay(7000);
24229110789Snakayama 	val = teliosio_mbu_read(tc);
24329110789Snakayama 	delay(7000);
24429110789Snakayama 
24529110789Snakayama 	return val;
24629110789Snakayama }
24729110789Snakayama 
24829110789Snakayama #define WAIT (1000000 / TELIOSIO_BMU_CLOCK_FREQ / 2)
24929110789Snakayama 
25029110789Snakayama static void
teliosio_mbu_write(tx_chipset_tag_t tc,int val)25129110789Snakayama teliosio_mbu_write(tx_chipset_tag_t tc, int val)
25229110789Snakayama {
25329110789Snakayama 	txreg_t reg;
25429110789Snakayama 	int s;
25529110789Snakayama 	int mask;
25629110789Snakayama 
25729110789Snakayama 	for (mask = 0x80; mask != 0; mask >>= 1) {
25829110789Snakayama 		s = splhigh();
25929110789Snakayama 		reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG);
26029110789Snakayama 		reg |= TELIOSIO_BMU_CLOCK;
26129110789Snakayama 		if (val & mask)
26229110789Snakayama 			reg |= TELIOSIO_BMU_DATAOUT;
26329110789Snakayama 		else
26429110789Snakayama 			reg &= ~TELIOSIO_BMU_DATAOUT;
26529110789Snakayama 		tx_conf_write(tc, TX392X_IODATAINOUT_REG, reg);
26629110789Snakayama 		splx(s);
26729110789Snakayama 		delay(WAIT);
26829110789Snakayama 
26929110789Snakayama 		s = splhigh();
27029110789Snakayama 		reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG);
27129110789Snakayama 		reg &= ~TELIOSIO_BMU_CLOCK;
27229110789Snakayama 		tx_conf_write(tc, TX392X_IODATAINOUT_REG, reg);
27329110789Snakayama 		splx(s);
27429110789Snakayama 		delay(WAIT);
27529110789Snakayama 	}
27629110789Snakayama }
27729110789Snakayama 
27829110789Snakayama static int
teliosio_mbu_read(tx_chipset_tag_t tc)27929110789Snakayama teliosio_mbu_read(tx_chipset_tag_t tc)
28029110789Snakayama {
28129110789Snakayama 	txreg_t reg;
28229110789Snakayama 	int s;
28329110789Snakayama 	int mask, val;
28429110789Snakayama 
28529110789Snakayama 	val = 0;
28629110789Snakayama 	for (mask = 0x80; mask != 0; mask >>= 1) {
28729110789Snakayama 		s = splhigh();
28829110789Snakayama 		reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG);
28929110789Snakayama 		reg |= TELIOSIO_BMU_CLOCK;
29029110789Snakayama 		tx_conf_write(tc, TX392X_IODATAINOUT_REG, reg);
29129110789Snakayama 		splx(s);
29229110789Snakayama 		delay(WAIT);
29329110789Snakayama 
29429110789Snakayama 		s = splhigh();
29529110789Snakayama 		reg = tx_conf_read(tc, TX392X_IODATAINOUT_REG);
29629110789Snakayama 		if (!(reg & TELIOSIO_BMU_DATAIN))
29729110789Snakayama 			val |= mask;
29829110789Snakayama 		reg &= ~TELIOSIO_BMU_CLOCK;
29929110789Snakayama 		tx_conf_write(tc, TX392X_IODATAINOUT_REG, reg);
30029110789Snakayama 		splx(s);
30129110789Snakayama 		delay(WAIT);
30229110789Snakayama 	}
30329110789Snakayama 
30429110789Snakayama 	return val;
30529110789Snakayama }
30629110789Snakayama #endif /* NAPMDEV */
307