Home | History | Annotate | Line # | Download | only in dev
zapm.c revision 1.12.62.1
      1  1.12.62.1   thorpej /*	$NetBSD: zapm.c,v 1.12.62.1 2021/03/23 07:14:52 thorpej Exp $	*/
      2        1.3    nonaka /*	$OpenBSD: zaurus_apm.c,v 1.13 2006/12/12 23:14:28 dim Exp $	*/
      3        1.1      ober 
      4        1.1      ober /*
      5        1.1      ober  * Copyright (c) 2005 Uwe Stuehler <uwe (at) bsdx.de>
      6        1.1      ober  *
      7        1.1      ober  * Permission to use, copy, modify, and distribute this software for any
      8        1.1      ober  * purpose with or without fee is hereby granted, provided that the above
      9        1.1      ober  * copyright notice and this permission notice appear in all copies.
     10        1.1      ober  *
     11        1.1      ober  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12        1.1      ober  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13        1.1      ober  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14        1.1      ober  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15        1.1      ober  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16        1.1      ober  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17        1.1      ober  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18        1.1      ober  */
     19        1.1      ober 
     20        1.3    nonaka #include <sys/cdefs.h>
     21  1.12.62.1   thorpej __KERNEL_RCSID(0, "$NetBSD: zapm.c,v 1.12.62.1 2021/03/23 07:14:52 thorpej Exp $");
     22        1.3    nonaka 
     23        1.1      ober #include <sys/param.h>
     24        1.1      ober #include <sys/systm.h>
     25        1.1      ober #include <sys/kernel.h>
     26        1.3    nonaka #include <sys/callout.h>
     27        1.6       uwe #include <sys/selinfo.h> /* XXX: for apm_softc that is exposed here */
     28       1.10  uebayasi #include <sys/device.h>
     29        1.3    nonaka 
     30        1.3    nonaka #include <dev/hpc/apm/apmvar.h>
     31        1.1      ober 
     32        1.1      ober #include <arm/xscale/pxa2x0reg.h>
     33        1.1      ober #include <arm/xscale/pxa2x0var.h>
     34        1.3    nonaka #include <arm/xscale/pxa2x0cpu.h>
     35        1.1      ober #include <arm/xscale/pxa2x0_gpio.h>
     36        1.1      ober 
     37        1.3    nonaka #include <machine/config_hook.h>
     38        1.1      ober 
     39        1.3    nonaka #include <zaurus/dev/scoopvar.h>
     40        1.3    nonaka #include <zaurus/dev/zsspvar.h>
     41        1.3    nonaka #include <zaurus/zaurus/zaurus_reg.h>
     42        1.3    nonaka #include <zaurus/zaurus/zaurus_var.h>
     43        1.1      ober 
     44        1.3    nonaka #ifdef APMDEBUG
     45        1.1      ober #define DPRINTF(x)	printf x
     46        1.1      ober #else
     47        1.3    nonaka #define	DPRINTF(x)	do { } while (/*CONSTCOND*/0)
     48        1.1      ober #endif
     49        1.1      ober 
     50        1.1      ober struct zapm_softc {
     51        1.4    nonaka 	device_t sc_dev;
     52        1.3    nonaka 	void *sc_apmdev;
     53        1.8    nonaka 	kmutex_t sc_mtx;
     54        1.3    nonaka 
     55        1.3    nonaka 	struct callout sc_cyclic_poll;
     56        1.3    nonaka 	struct callout sc_discharge_poll;
     57        1.1      ober 	struct timeval sc_lastbattchk;
     58        1.3    nonaka 	volatile int suspended;
     59        1.3    nonaka 	volatile int charging;
     60        1.3    nonaka 	volatile int discharging;
     61        1.3    nonaka 	int battery_volt;
     62        1.3    nonaka 	int battery_full_cnt;
     63        1.3    nonaka 
     64        1.3    nonaka 	/* GPIO pin */
     65        1.3    nonaka 	int sc_ac_detect_pin;
     66        1.3    nonaka 	int sc_batt_cover_pin;
     67        1.3    nonaka 	int sc_charge_comp_pin;
     68        1.3    nonaka 
     69        1.3    nonaka 	/* machine-independent part */
     70        1.3    nonaka 	volatile u_int events;
     71        1.3    nonaka 	volatile int power_state;
     72        1.3    nonaka 	volatile int battery_state;
     73        1.3    nonaka 	volatile int ac_state;
     74        1.3    nonaka 	config_hook_tag sc_standby_hook;
     75        1.3    nonaka 	config_hook_tag sc_suspend_hook;
     76        1.3    nonaka 	config_hook_tag sc_battery_hook;
     77        1.3    nonaka 	config_hook_tag sc_ac_hook;
     78        1.3    nonaka 	int battery_life;
     79        1.3    nonaka 	int minutes_left;
     80        1.1      ober };
     81        1.1      ober 
     82        1.4    nonaka static int	zapm_match(device_t, cfdata_t, void *);
     83        1.4    nonaka static void	zapm_attach(device_t, device_t, void *);
     84        1.3    nonaka 
     85        1.4    nonaka CFATTACH_DECL_NEW(zapm, sizeof(struct zapm_softc),
     86        1.3    nonaka     zapm_match, zapm_attach, NULL, NULL);
     87        1.1      ober 
     88        1.3    nonaka static int	zapm_hook(void *, int, long, void *);
     89        1.3    nonaka static void     zapm_disconnect(void *);
     90        1.3    nonaka static void     zapm_enable(void *, int);
     91        1.3    nonaka static int      zapm_set_powstate(void *, u_int, u_int);
     92        1.6       uwe static int      zapm_get_powstat(void *, u_int, struct apm_power_info *);
     93        1.3    nonaka static int      zapm_get_event(void *, u_int *, u_int *);
     94        1.3    nonaka static void     zapm_cpu_busy(void *);
     95        1.3    nonaka static void     zapm_cpu_idle(void *);
     96        1.3    nonaka static void     zapm_get_capabilities(void *, u_int *, u_int *);
     97        1.3    nonaka 
     98        1.3    nonaka static struct apm_accessops zapm_accessops = {
     99        1.3    nonaka 	zapm_disconnect,
    100        1.3    nonaka 	zapm_enable,
    101        1.3    nonaka 	zapm_set_powstate,
    102        1.3    nonaka 	zapm_get_powstat,
    103        1.3    nonaka 	zapm_get_event,
    104        1.3    nonaka 	zapm_cpu_busy,
    105        1.3    nonaka 	zapm_cpu_idle,
    106        1.3    nonaka 	zapm_get_capabilities,
    107        1.1      ober };
    108        1.1      ober 
    109        1.3    nonaka static int	zapm_acintr(void *);
    110        1.3    nonaka static int	zapm_bcintr(void *);
    111        1.3    nonaka static void	zapm_cyclic(void *);
    112        1.3    nonaka static void	zapm_poll(void *);
    113        1.3    nonaka static void	zapm_poll1(void *, int);
    114        1.3    nonaka 
    115        1.3    nonaka /* battery-related GPIO pins */
    116        1.3    nonaka #define GPIO_AC_IN_C3000	115	/* 0=AC connected */
    117        1.3    nonaka #define GPIO_CHRG_CO_C3000	101	/* 1=battery full */
    118        1.3    nonaka #define GPIO_BATT_COVER_C3000	90	/* 0=unlocked */
    119        1.3    nonaka 
    120        1.3    nonaka /* Cyclic timer value */
    121        1.3    nonaka #define	CYCLIC_TIME	(60 * hz)	/* 60s */
    122        1.3    nonaka 
    123        1.3    nonaka static int
    124        1.4    nonaka zapm_match(device_t parent, cfdata_t cf, void *aux)
    125        1.3    nonaka {
    126        1.3    nonaka 
    127       1.11    nonaka 	if (ZAURUS_ISC1000 || ZAURUS_ISC3000)
    128       1.11    nonaka 		return 1;
    129       1.11    nonaka 	return 0;
    130        1.3    nonaka }
    131        1.3    nonaka 
    132        1.3    nonaka static void
    133        1.4    nonaka zapm_attach(device_t parent, device_t self, void *aux)
    134        1.3    nonaka {
    135        1.3    nonaka 	struct zapm_softc *sc = device_private(self);
    136        1.3    nonaka 	struct apmdev_attach_args aaa;
    137        1.3    nonaka 
    138        1.4    nonaka 	sc->sc_dev = self;
    139        1.4    nonaka 
    140        1.3    nonaka 	aprint_normal(": pseudo power management module\n");
    141        1.4    nonaka 	aprint_naive("\n");
    142        1.3    nonaka 
    143        1.3    nonaka 	/* machine-depent part */
    144        1.3    nonaka 	callout_init(&sc->sc_cyclic_poll, 0);
    145        1.3    nonaka 	callout_setfunc(&sc->sc_cyclic_poll, zapm_cyclic, sc);
    146        1.3    nonaka 	callout_init(&sc->sc_discharge_poll, 0);
    147        1.3    nonaka 	callout_setfunc(&sc->sc_discharge_poll, zapm_poll, sc);
    148        1.8    nonaka 	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
    149        1.3    nonaka 
    150       1.11    nonaka 	if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
    151        1.3    nonaka 		sc->sc_ac_detect_pin = GPIO_AC_IN_C3000;
    152        1.3    nonaka 		sc->sc_batt_cover_pin = GPIO_BATT_COVER_C3000;
    153        1.3    nonaka 		sc->sc_charge_comp_pin = GPIO_CHRG_CO_C3000;
    154        1.3    nonaka 	} else {
    155        1.3    nonaka 		/* XXX */
    156        1.3    nonaka 		return;
    157        1.3    nonaka 	}
    158        1.3    nonaka 
    159        1.3    nonaka 	pxa2x0_gpio_set_function(sc->sc_ac_detect_pin, GPIO_IN);
    160        1.3    nonaka 	pxa2x0_gpio_set_function(sc->sc_charge_comp_pin, GPIO_IN);
    161        1.3    nonaka 	pxa2x0_gpio_set_function(sc->sc_batt_cover_pin, GPIO_IN);
    162        1.3    nonaka 
    163        1.3    nonaka 	(void)pxa2x0_gpio_intr_establish(sc->sc_ac_detect_pin,
    164        1.3    nonaka 	    IST_EDGE_BOTH, IPL_BIO, zapm_acintr, sc);
    165        1.3    nonaka 	(void)pxa2x0_gpio_intr_establish(sc->sc_charge_comp_pin,
    166        1.3    nonaka 	    IST_EDGE_BOTH, IPL_BIO, zapm_bcintr, sc);
    167        1.3    nonaka 
    168        1.3    nonaka 	/* machine-independent part */
    169        1.3    nonaka 	sc->events = 0;
    170        1.3    nonaka 	sc->power_state = APM_SYS_READY;
    171        1.3    nonaka 	sc->battery_state = APM_BATT_FLAG_UNKNOWN;
    172        1.3    nonaka 	sc->ac_state = APM_AC_UNKNOWN;
    173        1.3    nonaka 	sc->battery_life = APM_BATT_LIFE_UNKNOWN;
    174        1.3    nonaka 	sc->minutes_left = 0;
    175        1.3    nonaka 	sc->sc_standby_hook = config_hook(CONFIG_HOOK_PMEVENT,
    176        1.3    nonaka 					  CONFIG_HOOK_PMEVENT_STANDBYREQ,
    177        1.3    nonaka 					  CONFIG_HOOK_EXCLUSIVE,
    178        1.3    nonaka 					  zapm_hook, sc);
    179        1.3    nonaka 	sc->sc_suspend_hook = config_hook(CONFIG_HOOK_PMEVENT,
    180        1.3    nonaka 					  CONFIG_HOOK_PMEVENT_SUSPENDREQ,
    181        1.3    nonaka 					  CONFIG_HOOK_EXCLUSIVE,
    182        1.3    nonaka 					  zapm_hook, sc);
    183        1.3    nonaka 
    184        1.3    nonaka 	sc->sc_battery_hook = config_hook(CONFIG_HOOK_PMEVENT,
    185        1.3    nonaka 					  CONFIG_HOOK_PMEVENT_BATTERY,
    186        1.3    nonaka 					  CONFIG_HOOK_SHARE,
    187        1.3    nonaka 					  zapm_hook, sc);
    188        1.3    nonaka 
    189        1.3    nonaka 	sc->sc_ac_hook = config_hook(CONFIG_HOOK_PMEVENT,
    190        1.3    nonaka 				     CONFIG_HOOK_PMEVENT_AC,
    191        1.3    nonaka 				     CONFIG_HOOK_SHARE,
    192        1.3    nonaka 				     zapm_hook, sc);
    193        1.3    nonaka 
    194        1.3    nonaka 	aaa.accessops = &zapm_accessops;
    195        1.3    nonaka 	aaa.accesscookie = sc;
    196        1.3    nonaka 	aaa.apm_detail = 0x0102;
    197        1.3    nonaka 
    198  1.12.62.1   thorpej 	sc->sc_apmdev = config_found(self, &aaa, apmprint, CFARG_EOL);
    199        1.3    nonaka 	if (sc->sc_apmdev != NULL) {
    200        1.3    nonaka 		zapm_poll1(sc, 0);
    201        1.3    nonaka 		callout_schedule(&sc->sc_cyclic_poll, CYCLIC_TIME);
    202        1.3    nonaka 	}
    203        1.3    nonaka }
    204        1.3    nonaka 
    205        1.3    nonaka static int
    206        1.3    nonaka zapm_hook(void *v, int type, long id, void *msg)
    207        1.3    nonaka {
    208        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    209        1.3    nonaka 	int charge;
    210        1.3    nonaka 	int message;
    211        1.3    nonaka 	int s;
    212        1.3    nonaka 
    213        1.3    nonaka 	if (type != CONFIG_HOOK_PMEVENT)
    214        1.3    nonaka 		return 1;
    215        1.3    nonaka 
    216        1.3    nonaka 	if (CONFIG_HOOK_VALUEP(msg))
    217        1.3    nonaka 		message = (int)msg;
    218        1.3    nonaka 	else
    219        1.3    nonaka 		message = *(int *)msg;
    220        1.3    nonaka 
    221        1.3    nonaka 	s = splhigh();
    222        1.3    nonaka 
    223        1.3    nonaka 	switch (id) {
    224        1.3    nonaka 	case CONFIG_HOOK_PMEVENT_STANDBYREQ:
    225        1.3    nonaka 		if (sc->power_state != APM_SYS_STANDBY) {
    226        1.3    nonaka 			sc->events |= (1 << APM_USER_STANDBY_REQ);
    227        1.3    nonaka 		} else {
    228        1.3    nonaka 			sc->events |= (1 << APM_NORMAL_RESUME);
    229        1.3    nonaka 		}
    230        1.3    nonaka 		break;
    231        1.3    nonaka 	case CONFIG_HOOK_PMEVENT_SUSPENDREQ:
    232        1.3    nonaka 		if (sc->power_state != APM_SYS_SUSPEND) {
    233        1.3    nonaka 			DPRINTF(("zapm: suspend request\n"));
    234        1.3    nonaka 			sc->events |= (1 << APM_USER_SUSPEND_REQ);
    235        1.3    nonaka 		} else {
    236        1.3    nonaka 			sc->events |= (1 << APM_NORMAL_RESUME);
    237        1.3    nonaka 		}
    238        1.3    nonaka 		break;
    239        1.3    nonaka 	case CONFIG_HOOK_PMEVENT_BATTERY:
    240        1.3    nonaka 		switch (message) {
    241        1.3    nonaka 		case CONFIG_HOOK_BATT_CRITICAL:
    242        1.3    nonaka 			DPRINTF(("zapm: battery state critical\n"));
    243        1.3    nonaka 			charge = sc->battery_state & APM_BATT_FLAG_CHARGING;
    244        1.3    nonaka 			sc->battery_state = APM_BATT_FLAG_CRITICAL;
    245        1.3    nonaka 			sc->battery_state |= charge;
    246        1.3    nonaka 			sc->battery_life = 0;
    247        1.3    nonaka 			break;
    248        1.3    nonaka 		case CONFIG_HOOK_BATT_LOW:
    249        1.3    nonaka 			DPRINTF(("zapm: battery state low\n"));
    250        1.3    nonaka 			charge = sc->battery_state & APM_BATT_FLAG_CHARGING;
    251        1.3    nonaka 			sc->battery_state = APM_BATT_FLAG_LOW;
    252        1.3    nonaka 			sc->battery_state |= charge;
    253        1.3    nonaka 			break;
    254        1.3    nonaka 		case CONFIG_HOOK_BATT_HIGH:
    255        1.3    nonaka 			DPRINTF(("zapm: battery state high\n"));
    256        1.3    nonaka 			charge = sc->battery_state & APM_BATT_FLAG_CHARGING;
    257        1.3    nonaka 			sc->battery_state = APM_BATT_FLAG_HIGH;
    258        1.3    nonaka 			sc->battery_state |= charge;
    259        1.3    nonaka 			break;
    260        1.3    nonaka 		case CONFIG_HOOK_BATT_10P:
    261        1.3    nonaka 			DPRINTF(("zapm: battery life 10%%\n"));
    262        1.3    nonaka 			sc->battery_life = 10;
    263        1.3    nonaka 			break;
    264        1.3    nonaka 		case CONFIG_HOOK_BATT_20P:
    265        1.3    nonaka 			DPRINTF(("zapm: battery life 20%%\n"));
    266        1.3    nonaka 			sc->battery_life = 20;
    267        1.3    nonaka 			break;
    268        1.3    nonaka 		case CONFIG_HOOK_BATT_30P:
    269        1.3    nonaka 			DPRINTF(("zapm: battery life 30%%\n"));
    270        1.3    nonaka 			sc->battery_life = 30;
    271        1.3    nonaka 			break;
    272        1.3    nonaka 		case CONFIG_HOOK_BATT_40P:
    273        1.3    nonaka 			DPRINTF(("zapm: battery life 40%%\n"));
    274        1.3    nonaka 			sc->battery_life = 40;
    275        1.3    nonaka 			break;
    276        1.3    nonaka 		case CONFIG_HOOK_BATT_50P:
    277        1.3    nonaka 			DPRINTF(("zapm: battery life 50%%\n"));
    278        1.3    nonaka 			sc->battery_life = 50;
    279        1.3    nonaka 			break;
    280        1.3    nonaka 		case CONFIG_HOOK_BATT_60P:
    281        1.3    nonaka 			DPRINTF(("zapm: battery life 60%%\n"));
    282        1.3    nonaka 			sc->battery_life = 60;
    283        1.3    nonaka 			break;
    284        1.3    nonaka 		case CONFIG_HOOK_BATT_70P:
    285        1.3    nonaka 			DPRINTF(("zapm: battery life 70%%\n"));
    286        1.3    nonaka 			sc->battery_life = 70;
    287        1.3    nonaka 			break;
    288        1.3    nonaka 		case CONFIG_HOOK_BATT_80P:
    289        1.3    nonaka 			DPRINTF(("zapm: battery life 80%%\n"));
    290        1.3    nonaka 			sc->battery_life = 80;
    291        1.3    nonaka 			break;
    292        1.3    nonaka 		case CONFIG_HOOK_BATT_90P:
    293        1.3    nonaka 			DPRINTF(("zapm: battery life 90%%\n"));
    294        1.3    nonaka 			sc->battery_life = 90;
    295        1.3    nonaka 			break;
    296        1.3    nonaka 		case CONFIG_HOOK_BATT_100P:
    297        1.3    nonaka 			DPRINTF(("zapm: battery life 100%%\n"));
    298        1.3    nonaka 			sc->battery_life = 100;
    299        1.3    nonaka 			break;
    300        1.3    nonaka 		case CONFIG_HOOK_BATT_UNKNOWN:
    301        1.3    nonaka 			DPRINTF(("zapm: battery state unknown\n"));
    302        1.3    nonaka 			sc->battery_state = APM_BATT_FLAG_UNKNOWN;
    303        1.3    nonaka 			sc->battery_life = APM_BATT_LIFE_UNKNOWN;
    304        1.3    nonaka 			break;
    305        1.3    nonaka 		case CONFIG_HOOK_BATT_NO_SYSTEM_BATTERY:
    306        1.3    nonaka 			DPRINTF(("zapm: battery state no system battery?\n"));
    307        1.3    nonaka 			sc->battery_state = APM_BATT_FLAG_NO_SYSTEM_BATTERY;
    308        1.3    nonaka 			sc->battery_life = APM_BATT_LIFE_UNKNOWN;
    309        1.3    nonaka 			break;
    310        1.3    nonaka 		}
    311        1.3    nonaka 		break;
    312        1.3    nonaka 	case CONFIG_HOOK_PMEVENT_AC:
    313        1.3    nonaka 		switch (message) {
    314        1.3    nonaka 		case CONFIG_HOOK_AC_OFF:
    315        1.3    nonaka 			DPRINTF(("zapm: ac not connected\n"));
    316        1.3    nonaka 			sc->battery_state &= ~APM_BATT_FLAG_CHARGING;
    317        1.3    nonaka 			sc->ac_state = APM_AC_OFF;
    318        1.3    nonaka 			break;
    319        1.3    nonaka 		case CONFIG_HOOK_AC_ON_CHARGE:
    320        1.3    nonaka 			DPRINTF(("zapm: charging\n"));
    321        1.3    nonaka 			sc->battery_state |= APM_BATT_FLAG_CHARGING;
    322        1.3    nonaka 			sc->ac_state = APM_AC_ON;
    323        1.3    nonaka 			break;
    324        1.3    nonaka 		case CONFIG_HOOK_AC_ON_NOCHARGE:
    325        1.3    nonaka 			DPRINTF(("zapm: ac connected\n"));
    326        1.3    nonaka 			sc->battery_state &= ~APM_BATT_FLAG_CHARGING;
    327        1.3    nonaka 			sc->ac_state = APM_AC_ON;
    328        1.3    nonaka 			break;
    329        1.3    nonaka 		case CONFIG_HOOK_AC_UNKNOWN:
    330        1.3    nonaka 			sc->ac_state = APM_AC_UNKNOWN;
    331        1.3    nonaka 			break;
    332        1.3    nonaka 		}
    333        1.3    nonaka 		break;
    334        1.3    nonaka 	}
    335        1.3    nonaka 
    336        1.3    nonaka 	splx(s);
    337        1.3    nonaka 
    338        1.3    nonaka 	return 0;
    339        1.3    nonaka }
    340        1.3    nonaka 
    341        1.3    nonaka static void
    342        1.3    nonaka zapm_disconnect(void *v)
    343        1.3    nonaka {
    344        1.3    nonaka #if 0
    345        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    346        1.3    nonaka #endif
    347        1.3    nonaka }
    348        1.3    nonaka 
    349        1.3    nonaka static void
    350        1.3    nonaka zapm_enable(void *v, int onoff)
    351        1.3    nonaka {
    352        1.3    nonaka #if 0
    353        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    354        1.3    nonaka #endif
    355        1.3    nonaka }
    356        1.3    nonaka 
    357        1.3    nonaka static int
    358        1.3    nonaka zapm_set_powstate(void *v, u_int devid, u_int powstat)
    359        1.3    nonaka {
    360        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    361        1.3    nonaka 
    362        1.3    nonaka 	if (devid != APM_DEV_ALLDEVS)
    363        1.3    nonaka 		return APM_ERR_UNRECOG_DEV;
    364        1.3    nonaka 
    365        1.3    nonaka 	switch (powstat) {
    366        1.3    nonaka 	case APM_SYS_READY:
    367        1.3    nonaka 		DPRINTF(("zapm: set power state READY\n"));
    368        1.3    nonaka 		sc->power_state = APM_SYS_READY;
    369        1.3    nonaka 		break;
    370        1.3    nonaka 	case APM_SYS_STANDBY:
    371        1.3    nonaka 		DPRINTF(("zapm: set power state STANDBY\n"));
    372        1.3    nonaka 		/* XXX */
    373        1.3    nonaka 		DPRINTF(("zapm: resume\n"));
    374        1.3    nonaka 		break;
    375        1.3    nonaka 	case APM_SYS_SUSPEND:
    376        1.3    nonaka 		DPRINTF(("zapm: set power state SUSPEND...\n"));
    377        1.3    nonaka 		/* XXX */
    378        1.3    nonaka 		DPRINTF(("zapm: resume\n"));
    379        1.3    nonaka 		break;
    380        1.3    nonaka 	case APM_SYS_OFF:
    381        1.3    nonaka 		DPRINTF(("zapm: set power state OFF\n"));
    382        1.3    nonaka 		sc->power_state = APM_SYS_OFF;
    383        1.3    nonaka 		break;
    384        1.3    nonaka 	case APM_LASTREQ_INPROG:
    385        1.3    nonaka 		/*DPRINTF(("zapm: set power state INPROG\n"));*/
    386        1.3    nonaka 		break;
    387        1.3    nonaka 	case APM_LASTREQ_REJECTED:
    388        1.3    nonaka 		DPRINTF(("zapm: set power state REJECTED\n"));
    389        1.3    nonaka 		break;
    390        1.3    nonaka 	}
    391        1.3    nonaka 
    392        1.3    nonaka 	return 0;
    393        1.3    nonaka }
    394        1.3    nonaka 
    395        1.3    nonaka static int
    396        1.6       uwe zapm_get_powstat(void *v, u_int batteryid, struct apm_power_info *pinfo)
    397        1.3    nonaka {
    398        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    399        1.3    nonaka 	int val;
    400        1.3    nonaka 
    401        1.3    nonaka 	if (config_hook_call(CONFIG_HOOK_GET,
    402        1.3    nonaka 			     CONFIG_HOOK_ACADAPTER, &val) != -1)
    403        1.3    nonaka 		pinfo->ac_state = val;
    404        1.3    nonaka 	else
    405        1.3    nonaka 		pinfo->ac_state = sc->ac_state;
    406        1.9    nonaka 	DPRINTF(("zapm: pinfo->ac_state: %d\n", pinfo->ac_state));
    407        1.9    nonaka 
    408        1.3    nonaka 	if (config_hook_call(CONFIG_HOOK_GET,
    409        1.3    nonaka 			     CONFIG_HOOK_CHARGE, &val) != -1)
    410        1.3    nonaka 		pinfo->battery_state = val;
    411        1.9    nonaka 	else {
    412        1.9    nonaka 		DPRINTF(("zapm: sc->battery_state: %#x\n", sc->battery_state));
    413        1.9    nonaka 		if (sc->battery_state & APM_BATT_FLAG_CHARGING)
    414        1.9    nonaka 			pinfo->battery_flags = APM_BATT_FLAG_CHARGING;
    415        1.9    nonaka 		else if (sc->battery_state & APM_BATT_FLAG_CRITICAL)
    416        1.9    nonaka 			pinfo->battery_flags = APM_BATT_FLAG_CRITICAL;
    417        1.9    nonaka 		else if (sc->battery_state & APM_BATT_FLAG_LOW)
    418        1.9    nonaka 			pinfo->battery_flags = APM_BATT_FLAG_LOW;
    419        1.9    nonaka 		else if (sc->battery_state & APM_BATT_FLAG_HIGH)
    420        1.9    nonaka 			pinfo->battery_flags = APM_BATT_FLAG_HIGH;
    421        1.9    nonaka 		else
    422        1.9    nonaka 			pinfo->battery_flags = APM_BATT_FLAG_UNKNOWN;
    423        1.9    nonaka 	}
    424        1.9    nonaka 	DPRINTF(("zapm: pinfo->battery_flags: %#x\n", pinfo->battery_flags));
    425        1.9    nonaka 
    426        1.3    nonaka 	if (config_hook_call(CONFIG_HOOK_GET,
    427        1.3    nonaka 			     CONFIG_HOOK_BATTERYVAL, &val) != -1)
    428        1.3    nonaka 		pinfo->battery_life = val;
    429        1.3    nonaka 	else
    430        1.3    nonaka 		pinfo->battery_life = sc->battery_life;
    431        1.9    nonaka 	DPRINTF(("zapm: pinfo->battery_life: %d\n", pinfo->battery_life));
    432        1.3    nonaka 
    433        1.3    nonaka 	return 0;
    434        1.3    nonaka }
    435        1.3    nonaka 
    436        1.3    nonaka static int
    437        1.3    nonaka zapm_get_event(void *v, u_int *event_type, u_int *event_info)
    438        1.3    nonaka {
    439        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    440        1.3    nonaka 	u_int ev;
    441        1.3    nonaka 	int s;
    442        1.3    nonaka 
    443        1.3    nonaka 	s = splhigh();
    444        1.3    nonaka 	for (ev = APM_STANDBY_REQ; ev <= APM_CAP_CHANGE; ev++) {
    445        1.3    nonaka 		if (sc->events & (1 << ev)) {
    446        1.3    nonaka 			sc->events &= ~(1 << ev);
    447        1.3    nonaka 			*event_type = ev;
    448        1.3    nonaka 			if (*event_type == APM_NORMAL_RESUME ||
    449        1.3    nonaka 			    *event_type == APM_CRIT_RESUME) {
    450        1.3    nonaka 				/* pccard power off in the suspend state */
    451        1.3    nonaka 				*event_info = 1;
    452        1.3    nonaka 				sc->power_state = APM_SYS_READY;
    453        1.3    nonaka 			} else {
    454        1.3    nonaka 				*event_info = 0;
    455        1.3    nonaka 			}
    456        1.3    nonaka 			splx(s);
    457        1.3    nonaka 
    458        1.3    nonaka 			return 0;
    459        1.3    nonaka 		}
    460        1.3    nonaka 	}
    461        1.3    nonaka 	splx(s);
    462        1.3    nonaka 
    463        1.3    nonaka 	return APM_ERR_NOEVENTS;
    464        1.3    nonaka }
    465        1.3    nonaka 
    466        1.3    nonaka static void
    467        1.3    nonaka zapm_cpu_busy(void *v)
    468        1.3    nonaka {
    469        1.3    nonaka #if 0
    470        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    471        1.3    nonaka #endif
    472        1.3    nonaka }
    473        1.3    nonaka 
    474        1.3    nonaka static void
    475        1.3    nonaka zapm_cpu_idle(void *v)
    476        1.3    nonaka {
    477        1.3    nonaka #if 0
    478        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    479        1.3    nonaka #endif
    480        1.3    nonaka }
    481        1.3    nonaka 
    482        1.3    nonaka static void
    483        1.3    nonaka zapm_get_capabilities(void *v, u_int *numbatts, u_int *capflags)
    484        1.3    nonaka {
    485        1.3    nonaka #if 0
    486        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    487        1.3    nonaka #endif
    488        1.3    nonaka 
    489        1.3    nonaka 	*numbatts = 1;
    490        1.3    nonaka 	*capflags = 0 /* | APM_GLOBAL_STANDBY | APM_GLOBAL_SUSPEND */;
    491        1.3    nonaka }
    492        1.3    nonaka 
    493        1.3    nonaka /*-----------------------------------------------------------------------------
    494        1.3    nonaka  * zaurus depent part
    495        1.3    nonaka  */
    496        1.1      ober /* MAX1111 command word */
    497        1.1      ober #define MAXCTRL_PD0		(1<<0)
    498        1.1      ober #define MAXCTRL_PD1		(1<<1)
    499        1.1      ober #define MAXCTRL_SGL		(1<<2)
    500        1.1      ober #define MAXCTRL_UNI		(1<<3)
    501        1.1      ober #define MAXCTRL_SEL_SHIFT	4
    502        1.1      ober #define MAXCTRL_STR		(1<<7)
    503        1.1      ober 
    504        1.1      ober /* MAX1111 ADC channels */
    505        1.1      ober #define	BATT_THM		2
    506        1.1      ober #define	BATT_AD			4
    507        1.1      ober #define JK_VAD			6
    508        1.1      ober 
    509        1.1      ober /*
    510        1.1      ober  * Battery-specific information
    511        1.1      ober  */
    512        1.1      ober struct battery_threshold {
    513        1.3    nonaka 	int	percent;
    514        1.3    nonaka 	int	value;
    515        1.3    nonaka 	int	state;
    516        1.1      ober };
    517        1.1      ober 
    518        1.1      ober struct battery_info {
    519        1.3    nonaka 	const struct battery_threshold *bi_thres;
    520        1.1      ober };
    521        1.1      ober 
    522        1.3    nonaka static const struct battery_threshold zaurus_battery_life_c3000[] = {
    523        1.5    nonaka 	{ 100,	212,	CONFIG_HOOK_BATT_HIGH		},
    524        1.5    nonaka 	{  98,	212,	CONFIG_HOOK_BATT_HIGH		},
    525        1.5    nonaka 	{  95,	211,	CONFIG_HOOK_BATT_HIGH		},
    526        1.5    nonaka 	{  93,	210,	CONFIG_HOOK_BATT_HIGH		},
    527        1.5    nonaka 	{  90,	209,	CONFIG_HOOK_BATT_HIGH		},
    528        1.5    nonaka 	{  88,	208,	CONFIG_HOOK_BATT_HIGH		},
    529        1.5    nonaka 	{  85,	207,	CONFIG_HOOK_BATT_HIGH		},
    530        1.5    nonaka 	{  83,	206,	CONFIG_HOOK_BATT_HIGH		},
    531        1.5    nonaka 	{  80,	205,	CONFIG_HOOK_BATT_HIGH		},
    532        1.5    nonaka 	{  78,	204,	CONFIG_HOOK_BATT_HIGH		},
    533        1.5    nonaka 	{  75,	203,	CONFIG_HOOK_BATT_HIGH		},
    534        1.5    nonaka 	{  73,	202,	CONFIG_HOOK_BATT_HIGH		},
    535        1.5    nonaka 	{  70,	201,	CONFIG_HOOK_BATT_HIGH		},
    536        1.5    nonaka 	{  68,	200,	CONFIG_HOOK_BATT_HIGH		},
    537        1.5    nonaka 	{  65,	199,	CONFIG_HOOK_BATT_HIGH		},
    538        1.5    nonaka 	{  63,	198,	CONFIG_HOOK_BATT_HIGH		},
    539        1.5    nonaka 	{  60,	197,	CONFIG_HOOK_BATT_HIGH		},
    540        1.5    nonaka 	{  58,	196,	CONFIG_HOOK_BATT_HIGH		},
    541        1.5    nonaka 	{  55,	195,	CONFIG_HOOK_BATT_HIGH		},
    542        1.5    nonaka 	{  53,	194,	CONFIG_HOOK_BATT_HIGH		},
    543        1.5    nonaka 	{  50,	193,	CONFIG_HOOK_BATT_HIGH		},
    544        1.5    nonaka 	{  48,	192,	CONFIG_HOOK_BATT_HIGH		},
    545        1.5    nonaka 	{  45,	192,	CONFIG_HOOK_BATT_HIGH		},
    546        1.5    nonaka 	{  43,	191,	CONFIG_HOOK_BATT_HIGH		},
    547        1.5    nonaka 	{  40,	191,	CONFIG_HOOK_BATT_HIGH		},
    548        1.5    nonaka 	{  38,	190,	CONFIG_HOOK_BATT_HIGH		},
    549        1.5    nonaka 	{  35,	190,	CONFIG_HOOK_BATT_HIGH		},
    550        1.5    nonaka 	{  33,	189,	CONFIG_HOOK_BATT_HIGH		},
    551        1.5    nonaka 	{  30,	188,	CONFIG_HOOK_BATT_HIGH		},
    552        1.5    nonaka 	{  28,	187,	CONFIG_HOOK_BATT_LOW		},
    553        1.5    nonaka 	{  25,	186,	CONFIG_HOOK_BATT_LOW		},
    554        1.5    nonaka 	{  23,	185,	CONFIG_HOOK_BATT_LOW		},
    555        1.5    nonaka 	{  20,	184,	CONFIG_HOOK_BATT_LOW		},
    556        1.5    nonaka 	{  18,	183,	CONFIG_HOOK_BATT_LOW		},
    557        1.5    nonaka 	{  15,	182,	CONFIG_HOOK_BATT_LOW		},
    558        1.5    nonaka 	{  13,	181,	CONFIG_HOOK_BATT_LOW		},
    559        1.5    nonaka 	{  10,	180,	CONFIG_HOOK_BATT_LOW		},
    560        1.5    nonaka 	{   8,	179,	CONFIG_HOOK_BATT_LOW		},
    561        1.3    nonaka 	{   5,	178,	CONFIG_HOOK_BATT_LOW		},
    562        1.3    nonaka 	{   0,	  0,	CONFIG_HOOK_BATT_CRITICAL	}
    563        1.1      ober };
    564        1.1      ober 
    565        1.3    nonaka static const struct battery_info zaurus_battery_c3000 = {
    566        1.1      ober 	zaurus_battery_life_c3000
    567        1.1      ober };
    568        1.1      ober 
    569        1.3    nonaka static const struct battery_info *zaurus_main_battery = &zaurus_battery_c3000;
    570        1.1      ober 
    571        1.1      ober /* Restart charging this many times before accepting BATT_FULL. */
    572        1.3    nonaka #define	MIN_BATT_FULL		2
    573        1.1      ober 
    574        1.1      ober /* Discharge 100 ms before reading the voltage if AC is connected. */
    575        1.3    nonaka #define	DISCHARGE_TIMEOUT	(hz / 10)
    576        1.1      ober 
    577        1.1      ober /* Check battery voltage and "kick charging" every minute. */
    578        1.3    nonaka static const struct timeval zapm_battchkrate = { 60, 0 };
    579        1.3    nonaka 
    580        1.3    nonaka static int	zapm_get_ac_state(struct zapm_softc *);
    581        1.3    nonaka static int	zapm_get_battery_compartment_state(struct zapm_softc *);
    582        1.3    nonaka static int	zapm_get_charge_complete_state(struct zapm_softc *);
    583        1.3    nonaka static void	zapm_set_charging(struct zapm_softc *, int);
    584        1.3    nonaka static int	zapm_charge_complete(struct zapm_softc *);
    585        1.5    nonaka static int	max1111_adc_value_avg(int chan, int pause);
    586        1.3    nonaka static int	zapm_get_battery_volt(void);
    587        1.3    nonaka static int	zapm_battery_state(int volt);
    588        1.3    nonaka static int	zapm_battery_life(int volt);
    589        1.3    nonaka 
    590        1.3    nonaka static int
    591        1.3    nonaka zapm_acintr(void *v)
    592        1.3    nonaka {
    593        1.3    nonaka 
    594        1.3    nonaka 	zapm_poll1(v, 1);
    595        1.3    nonaka 
    596        1.3    nonaka 	return 1;
    597        1.3    nonaka }
    598        1.3    nonaka 
    599        1.3    nonaka static int
    600        1.3    nonaka zapm_bcintr(void *v)
    601        1.3    nonaka {
    602        1.3    nonaka 
    603        1.3    nonaka 	zapm_poll1(v, 1);
    604        1.1      ober 
    605        1.3    nonaka 	return 1;
    606        1.3    nonaka }
    607        1.3    nonaka 
    608        1.3    nonaka static void
    609        1.3    nonaka zapm_cyclic(void *v)
    610        1.3    nonaka {
    611        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    612        1.1      ober 
    613        1.3    nonaka 	zapm_poll1(sc, 1);
    614        1.3    nonaka 
    615        1.3    nonaka 	callout_schedule(&sc->sc_cyclic_poll, CYCLIC_TIME);
    616        1.3    nonaka }
    617        1.3    nonaka 
    618        1.3    nonaka static void
    619        1.3    nonaka zapm_poll(void *v)
    620        1.3    nonaka {
    621        1.1      ober 
    622        1.3    nonaka 	zapm_poll1(v, 1);
    623        1.3    nonaka }
    624        1.1      ober 
    625        1.3    nonaka static int
    626        1.3    nonaka zapm_get_ac_state(struct zapm_softc *sc)
    627        1.3    nonaka {
    628        1.1      ober 
    629        1.3    nonaka 	if (!pxa2x0_gpio_get_bit(sc->sc_ac_detect_pin))
    630        1.3    nonaka 		return APM_AC_ON;
    631        1.3    nonaka 	return APM_AC_OFF;
    632        1.1      ober }
    633        1.1      ober 
    634        1.3    nonaka static int
    635        1.3    nonaka zapm_get_battery_compartment_state(struct zapm_softc *sc)
    636        1.1      ober {
    637        1.1      ober 
    638        1.3    nonaka 	return pxa2x0_gpio_get_bit(sc->sc_batt_cover_pin);
    639        1.1      ober }
    640        1.1      ober 
    641        1.3    nonaka static int
    642        1.3    nonaka zapm_get_charge_complete_state(struct zapm_softc *sc)
    643        1.1      ober {
    644        1.3    nonaka 
    645        1.3    nonaka 	return pxa2x0_gpio_get_bit(sc->sc_charge_comp_pin);
    646        1.1      ober }
    647        1.1      ober 
    648        1.3    nonaka static void
    649        1.3    nonaka zapm_set_charging(struct zapm_softc *sc, int enable)
    650        1.1      ober {
    651        1.3    nonaka 
    652       1.12   tsutsui 	if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
    653       1.12   tsutsui 		scoop_discharge_battery(0);
    654       1.12   tsutsui 		scoop_charge_battery(enable, 0);
    655       1.12   tsutsui 		scoop_led_set(SCOOP_LED_ORANGE, enable);
    656       1.12   tsutsui 	}
    657        1.1      ober }
    658        1.1      ober 
    659        1.3    nonaka /*
    660        1.3    nonaka  * Return non-zero if the charge complete signal indicates that the
    661        1.3    nonaka  * battery is fully charged.  Restart charging to clear this signal.
    662        1.3    nonaka  */
    663        1.3    nonaka static int
    664        1.3    nonaka zapm_charge_complete(struct zapm_softc *sc)
    665        1.1      ober {
    666        1.3    nonaka 
    667        1.3    nonaka 	if (sc->charging && sc->battery_full_cnt < MIN_BATT_FULL) {
    668        1.3    nonaka 		if (zapm_get_charge_complete_state(sc)) {
    669        1.3    nonaka 			sc->battery_full_cnt++;
    670        1.3    nonaka 			if (sc->battery_full_cnt < MIN_BATT_FULL) {
    671        1.3    nonaka 				DPRINTF(("battery almost full\n"));
    672        1.3    nonaka 				zapm_set_charging(sc, 0);
    673        1.3    nonaka 				delay(15000);
    674        1.3    nonaka 				zapm_set_charging(sc, 1);
    675        1.3    nonaka 			}
    676        1.3    nonaka 		} else if (sc->battery_full_cnt > 0) {
    677        1.3    nonaka 			/* false alarm */
    678        1.3    nonaka 			sc->battery_full_cnt = 0;
    679        1.3    nonaka 			zapm_set_charging(sc, 0);
    680        1.3    nonaka 			delay(15000);
    681        1.3    nonaka 			zapm_set_charging(sc, 1);
    682        1.3    nonaka 		}
    683        1.3    nonaka 	}
    684        1.3    nonaka 
    685        1.3    nonaka 	return (sc->battery_full_cnt >= MIN_BATT_FULL);
    686        1.1      ober }
    687        1.1      ober 
    688        1.3    nonaka static int
    689        1.1      ober max1111_adc_value(int chan)
    690        1.1      ober {
    691        1.1      ober 
    692        1.1      ober 	return ((int)zssp_ic_send(ZSSP_IC_MAX1111, MAXCTRL_PD0 |
    693        1.1      ober 	    MAXCTRL_PD1 | MAXCTRL_SGL | MAXCTRL_UNI |
    694        1.1      ober 	    (chan << MAXCTRL_SEL_SHIFT) | MAXCTRL_STR));
    695        1.1      ober }
    696        1.1      ober 
    697        1.1      ober /* XXX simplify */
    698        1.3    nonaka static int
    699        1.1      ober max1111_adc_value_avg(int chan, int pause)
    700        1.1      ober {
    701        1.1      ober 	int val[5];
    702        1.5    nonaka 	int sum;
    703        1.5    nonaka 	int minv, maxv, v;
    704        1.5    nonaka 	int i;
    705        1.1      ober 
    706        1.3    nonaka 	DPRINTF(("max1111_adc_value_avg: chan = %d, pause = %d\n",
    707        1.3    nonaka 	    chan, pause));
    708        1.3    nonaka 
    709        1.1      ober 	for (i = 0; i < 5; i++) {
    710        1.1      ober 		val[i] = max1111_adc_value(chan);
    711        1.1      ober 		if (i != 4)
    712        1.1      ober 			delay(pause * 1000);
    713        1.3    nonaka 		DPRINTF(("max1111_adc_value_avg: chan[%d] = %d\n", i, val[i]));
    714        1.1      ober 	}
    715        1.1      ober 
    716        1.5    nonaka 	/* get max value */
    717        1.5    nonaka 	v = val[0];
    718        1.5    nonaka 	minv = 0;
    719        1.1      ober 	for (i = 1; i < 5; i++) {
    720        1.5    nonaka 		if (v < val[i]) {
    721        1.5    nonaka 			v = val[i];
    722        1.5    nonaka 			minv = i;
    723        1.1      ober 		}
    724        1.1      ober 	}
    725        1.1      ober 
    726        1.5    nonaka 	/* get min value */
    727        1.5    nonaka 	v = val[4];
    728        1.5    nonaka 	maxv = 4;
    729        1.1      ober 	for (i = 3; i >= 0; i--) {
    730        1.5    nonaka 		if (v > val[i]) {
    731        1.5    nonaka 			v = val[i];
    732        1.5    nonaka 			maxv = i;
    733        1.1      ober 		}
    734        1.1      ober 	}
    735        1.1      ober 
    736        1.5    nonaka 	DPRINTF(("max1111_adc_value_avg: minv = %d, maxv = %d\n", minv, maxv));
    737        1.5    nonaka 	sum = 0;
    738        1.1      ober 	for (i = 0; i < 5; i++) {
    739        1.5    nonaka 		if (i == minv || i == maxv)
    740        1.1      ober 			continue;
    741        1.1      ober 		sum += val[i];
    742        1.1      ober 	}
    743        1.1      ober 
    744        1.3    nonaka 	DPRINTF(("max1111_adc_value_avg: sum = %d, sum / 3 = %d\n",
    745        1.3    nonaka 	    sum, sum / 3));
    746        1.1      ober 
    747        1.3    nonaka 	return sum / 3;
    748        1.1      ober }
    749        1.1      ober 
    750        1.3    nonaka static int
    751        1.3    nonaka zapm_get_battery_volt(void)
    752        1.1      ober {
    753        1.1      ober 
    754        1.3    nonaka 	return max1111_adc_value_avg(BATT_AD, 10);
    755        1.1      ober }
    756        1.1      ober 
    757        1.3    nonaka static int
    758        1.3    nonaka zapm_battery_state(int volt)
    759        1.1      ober {
    760        1.1      ober 	const struct battery_threshold *bthr;
    761        1.1      ober 	int i;
    762        1.1      ober 
    763        1.1      ober 	bthr = zaurus_main_battery->bi_thres;
    764        1.1      ober 
    765        1.3    nonaka 	for (i = 0; bthr[i].value > 0; i++)
    766        1.3    nonaka 		if (bthr[i].value <= volt)
    767        1.1      ober 			break;
    768        1.1      ober 
    769        1.3    nonaka 	return bthr[i].state;
    770        1.1      ober }
    771        1.1      ober 
    772        1.3    nonaka static int
    773        1.3    nonaka zapm_battery_life(int volt)
    774        1.1      ober {
    775        1.1      ober 	const struct battery_threshold *bthr;
    776        1.1      ober 	int i;
    777        1.1      ober 
    778        1.1      ober 	bthr = zaurus_main_battery->bi_thres;
    779        1.1      ober 
    780        1.3    nonaka 	for (i = 0; bthr[i].value > 0; i++)
    781        1.3    nonaka 		if (bthr[i].value <= volt)
    782        1.1      ober 			break;
    783        1.1      ober 
    784        1.1      ober 	if (i == 0)
    785        1.3    nonaka 		return bthr[0].percent;
    786        1.1      ober 
    787        1.3    nonaka 	return (bthr[i].percent +
    788        1.3    nonaka 	    ((volt - bthr[i].value) * 100) /
    789        1.3    nonaka 	    (bthr[i-1].value - bthr[i].value) *
    790        1.3    nonaka 	    (bthr[i-1].percent - bthr[i].percent) / 100);
    791        1.1      ober }
    792        1.1      ober 
    793        1.1      ober /*
    794        1.1      ober  * Poll power-management related GPIO inputs, update battery life
    795        1.1      ober  * in softc, and/or control battery charging.
    796        1.1      ober  */
    797        1.3    nonaka static void
    798        1.3    nonaka zapm_poll1(void *v, int do_suspend)
    799        1.1      ober {
    800        1.3    nonaka 	struct zapm_softc *sc = (struct zapm_softc *)v;
    801        1.3    nonaka 	int ac_state;
    802        1.1      ober 	int bc_lock;
    803        1.1      ober 	int charging;
    804        1.1      ober 	int volt;
    805        1.1      ober 
    806        1.8    nonaka 	if (!mutex_tryenter(&sc->sc_mtx))
    807        1.8    nonaka 		return;
    808        1.1      ober 
    809        1.3    nonaka 	ac_state = zapm_get_ac_state(sc);
    810        1.3    nonaka 	bc_lock = zapm_get_battery_compartment_state(sc);
    811        1.1      ober 
    812        1.1      ober 	/* Stop discharging. */
    813        1.3    nonaka 	if (sc->discharging) {
    814        1.3    nonaka 		sc->discharging = 0;
    815        1.1      ober 		charging = 0;
    816        1.3    nonaka 		volt = zapm_get_battery_volt();
    817        1.1      ober 		DPRINTF(("zapm_poll: discharge off volt %d\n", volt));
    818        1.1      ober 	} else {
    819        1.3    nonaka 		charging = sc->battery_state & APM_BATT_FLAG_CHARGING;
    820        1.3    nonaka 		volt = sc->battery_volt;
    821        1.1      ober 	}
    822        1.1      ober 
    823        1.1      ober 	/* Start or stop charging as necessary. */
    824        1.3    nonaka 	if (ac_state && bc_lock) {
    825        1.3    nonaka 		int charge_completed = zapm_charge_complete(sc);
    826        1.1      ober 		if (charging) {
    827        1.3    nonaka 			if (charge_completed) {
    828        1.3    nonaka 				DPRINTF(("zapm_poll: battery is full\n"));
    829        1.1      ober 				charging = 0;
    830        1.3    nonaka 				zapm_set_charging(sc, 0);
    831        1.1      ober 			}
    832        1.3    nonaka 		} else if (!charge_completed) {
    833        1.7    nonaka 			charging = APM_BATT_FLAG_CHARGING;
    834        1.3    nonaka 			volt = zapm_get_battery_volt();
    835        1.3    nonaka 			zapm_set_charging(sc, 1);
    836        1.1      ober 			DPRINTF(("zapm_poll: start charging volt %d\n", volt));
    837        1.1      ober 		}
    838        1.1      ober 	} else {
    839        1.1      ober 		if (charging) {
    840        1.1      ober 			charging = 0;
    841        1.3    nonaka 			zapm_set_charging(sc, 0);
    842        1.1      ober 			timerclear(&sc->sc_lastbattchk);
    843        1.1      ober 			DPRINTF(("zapm_poll: stop charging\n"));
    844        1.1      ober 		}
    845        1.3    nonaka 		sc->battery_full_cnt = 0;
    846        1.1      ober 	}
    847        1.1      ober 
    848        1.1      ober 	/*
    849        1.1      ober 	 * Restart charging once in a while.  Discharge a few milliseconds
    850        1.1      ober 	 * before updating the voltage in our softc if A/C is connected.
    851        1.1      ober 	 */
    852        1.1      ober 	if (bc_lock && ratecheck(&sc->sc_lastbattchk, &zapm_battchkrate)) {
    853        1.3    nonaka 		if (do_suspend && sc->suspended) {
    854        1.3    nonaka 			/* XXX */
    855        1.3    nonaka #if 0
    856        1.1      ober 			DPRINTF(("zapm_poll: suspended %lu %lu\n",
    857        1.3    nonaka 			    sc->lastbattchk.tv_sec,
    858        1.1      ober 			    pxa2x0_rtc_getsecs()));
    859        1.1      ober 			if (charging) {
    860        1.3    nonaka 				zapm_set_charging(sc, 0);
    861        1.1      ober 				delay(15000);
    862        1.3    nonaka 				zapm_set_charging(sc, 1);
    863        1.1      ober 				pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() +
    864        1.1      ober 				    zapm_battchkrate.tv_sec + 1);
    865        1.1      ober 			}
    866        1.3    nonaka #endif
    867        1.3    nonaka 		} else if (ac_state && sc->battery_full_cnt == 0) {
    868        1.1      ober 			DPRINTF(("zapm_poll: discharge on\n"));
    869        1.1      ober 			if (charging)
    870        1.3    nonaka 				zapm_set_charging(sc, 0);
    871        1.3    nonaka 			sc->discharging = 1;
    872       1.12   tsutsui 			if (ZAURUS_ISC1000 || ZAURUS_ISC3000)
    873       1.12   tsutsui 				scoop_discharge_battery(1);
    874        1.3    nonaka 			callout_schedule(&sc->sc_discharge_poll,
    875        1.3    nonaka 			    DISCHARGE_TIMEOUT);
    876        1.3    nonaka 		} else if (!ac_state) {
    877        1.3    nonaka 			volt = zapm_get_battery_volt();
    878        1.1      ober 			DPRINTF(("zapm_poll: volt %d\n", volt));
    879        1.1      ober 		}
    880        1.1      ober 	}
    881        1.1      ober 
    882        1.1      ober 	/* Update the cached power state in our softc. */
    883        1.3    nonaka 	if ((ac_state != sc->ac_state)
    884        1.3    nonaka 	 || (charging != (sc->battery_state & APM_BATT_FLAG_CHARGING))) {
    885        1.3    nonaka 		config_hook_call(CONFIG_HOOK_PMEVENT,
    886        1.3    nonaka 		    CONFIG_HOOK_PMEVENT_AC,
    887        1.3    nonaka 		    (void *)((ac_state == APM_AC_OFF)
    888        1.3    nonaka 		        ? CONFIG_HOOK_AC_OFF
    889        1.3    nonaka 		        : (charging ? CONFIG_HOOK_AC_ON_CHARGE
    890        1.3    nonaka 		                    : CONFIG_HOOK_AC_ON_NOCHARGE)));
    891        1.3    nonaka 	}
    892        1.3    nonaka 	if (volt != sc->battery_volt) {
    893        1.3    nonaka 		sc->battery_volt = volt;
    894        1.3    nonaka 		sc->battery_life = zapm_battery_life(volt);
    895        1.3    nonaka 		config_hook_call(CONFIG_HOOK_PMEVENT,
    896        1.3    nonaka 		    CONFIG_HOOK_PMEVENT_BATTERY,
    897        1.3    nonaka 		    (void *)zapm_battery_state(volt));
    898        1.1      ober 	}
    899        1.1      ober 
    900        1.8    nonaka 	mutex_exit(&sc->sc_mtx);
    901        1.1      ober }
    902