Home | History | Annotate | Line # | Download | only in dev
zapm.c revision 1.12
      1  1.12   tsutsui /*	$NetBSD: zapm.c,v 1.12 2012/01/29 10:12:41 tsutsui 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   tsutsui __KERNEL_RCSID(0, "$NetBSD: zapm.c,v 1.12 2012/01/29 10:12:41 tsutsui 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.3    nonaka 	sc->sc_apmdev = config_found_ia(self, "apmdevif", &aaa, apmprint);
    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