1 /* $NetBSD: zapm.c,v 1.8 2009/12/12 13:12:49 nonaka Exp $ */
2 /* $OpenBSD: zaurus_apm.c,v 1.13 2006/12/12 23:14:28 dim Exp $ */
5 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: zapm.c,v 1.8 2009/12/12 13:12:49 nonaka Exp $");
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/kernel.h>
26 #include <sys/callout.h>
27 #include <sys/selinfo.h> /* XXX: for apm_softc that is exposed here */
29 #include <dev/hpc/apm/apmvar.h>
31 #include <arm/xscale/pxa2x0reg.h>
32 #include <arm/xscale/pxa2x0var.h>
33 #include <arm/xscale/pxa2x0cpu.h>
34 #include <arm/xscale/pxa2x0_gpio.h>
36 #include <machine/config_hook.h>
38 #include <zaurus/dev/scoopvar.h>
39 #include <zaurus/dev/zsspvar.h>
40 #include <zaurus/zaurus/zaurus_reg.h>
41 #include <zaurus/zaurus/zaurus_var.h>
44 #define DPRINTF(x) printf x
46 #define DPRINTF(x) do { } while (/*CONSTCOND*/0)
54 struct callout sc_cyclic_poll
;
55 struct callout sc_discharge_poll
;
56 struct timeval sc_lastbattchk
;
57 volatile int suspended
;
58 volatile int charging
;
59 volatile int discharging
;
65 int sc_batt_cover_pin
;
66 int sc_charge_comp_pin
;
68 /* machine-independent part */
69 volatile u_int events
;
70 volatile int power_state
;
71 volatile int battery_state
;
72 volatile int ac_state
;
73 config_hook_tag sc_standby_hook
;
74 config_hook_tag sc_suspend_hook
;
75 config_hook_tag sc_battery_hook
;
76 config_hook_tag sc_ac_hook
;
81 static int zapm_match(device_t
, cfdata_t
, void *);
82 static void zapm_attach(device_t
, device_t
, void *);
84 CFATTACH_DECL_NEW(zapm
, sizeof(struct zapm_softc
),
85 zapm_match
, zapm_attach
, NULL
, NULL
);
87 static int zapm_hook(void *, int, long, void *);
88 static void zapm_disconnect(void *);
89 static void zapm_enable(void *, int);
90 static int zapm_set_powstate(void *, u_int
, u_int
);
91 static int zapm_get_powstat(void *, u_int
, struct apm_power_info
*);
92 static int zapm_get_event(void *, u_int
*, u_int
*);
93 static void zapm_cpu_busy(void *);
94 static void zapm_cpu_idle(void *);
95 static void zapm_get_capabilities(void *, u_int
*, u_int
*);
97 static struct apm_accessops zapm_accessops
= {
105 zapm_get_capabilities
,
108 static int zapm_acintr(void *);
109 static int zapm_bcintr(void *);
110 static void zapm_cyclic(void *);
111 static void zapm_poll(void *);
112 static void zapm_poll1(void *, int);
114 /* battery-related GPIO pins */
115 #define GPIO_AC_IN_C3000 115 /* 0=AC connected */
116 #define GPIO_CHRG_CO_C3000 101 /* 1=battery full */
117 #define GPIO_BATT_COVER_C3000 90 /* 0=unlocked */
119 /* Cyclic timer value */
120 #define CYCLIC_TIME (60 * hz) /* 60s */
123 zapm_match(device_t parent
, cfdata_t cf
, void *aux
)
132 zapm_attach(device_t parent
, device_t self
, void *aux
)
134 struct zapm_softc
*sc
= device_private(self
);
135 struct apmdev_attach_args aaa
;
139 aprint_normal(": pseudo power management module\n");
142 /* machine-depent part */
143 callout_init(&sc
->sc_cyclic_poll
, 0);
144 callout_setfunc(&sc
->sc_cyclic_poll
, zapm_cyclic
, sc
);
145 callout_init(&sc
->sc_discharge_poll
, 0);
146 callout_setfunc(&sc
->sc_discharge_poll
, zapm_poll
, sc
);
147 mutex_init(&sc
->sc_mtx
, MUTEX_DEFAULT
, IPL_NONE
);
149 if (ZAURUS_ISC3000
) {
150 sc
->sc_ac_detect_pin
= GPIO_AC_IN_C3000
;
151 sc
->sc_batt_cover_pin
= GPIO_BATT_COVER_C3000
;
152 sc
->sc_charge_comp_pin
= GPIO_CHRG_CO_C3000
;
158 pxa2x0_gpio_set_function(sc
->sc_ac_detect_pin
, GPIO_IN
);
159 pxa2x0_gpio_set_function(sc
->sc_charge_comp_pin
, GPIO_IN
);
160 pxa2x0_gpio_set_function(sc
->sc_batt_cover_pin
, GPIO_IN
);
162 (void)pxa2x0_gpio_intr_establish(sc
->sc_ac_detect_pin
,
163 IST_EDGE_BOTH
, IPL_BIO
, zapm_acintr
, sc
);
164 (void)pxa2x0_gpio_intr_establish(sc
->sc_charge_comp_pin
,
165 IST_EDGE_BOTH
, IPL_BIO
, zapm_bcintr
, sc
);
167 /* machine-independent part */
169 sc
->power_state
= APM_SYS_READY
;
170 sc
->battery_state
= APM_BATT_FLAG_UNKNOWN
;
171 sc
->ac_state
= APM_AC_UNKNOWN
;
172 sc
->battery_life
= APM_BATT_LIFE_UNKNOWN
;
173 sc
->minutes_left
= 0;
174 sc
->sc_standby_hook
= config_hook(CONFIG_HOOK_PMEVENT
,
175 CONFIG_HOOK_PMEVENT_STANDBYREQ
,
176 CONFIG_HOOK_EXCLUSIVE
,
178 sc
->sc_suspend_hook
= config_hook(CONFIG_HOOK_PMEVENT
,
179 CONFIG_HOOK_PMEVENT_SUSPENDREQ
,
180 CONFIG_HOOK_EXCLUSIVE
,
183 sc
->sc_battery_hook
= config_hook(CONFIG_HOOK_PMEVENT
,
184 CONFIG_HOOK_PMEVENT_BATTERY
,
188 sc
->sc_ac_hook
= config_hook(CONFIG_HOOK_PMEVENT
,
189 CONFIG_HOOK_PMEVENT_AC
,
193 aaa
.accessops
= &zapm_accessops
;
194 aaa
.accesscookie
= sc
;
195 aaa
.apm_detail
= 0x0102;
197 sc
->sc_apmdev
= config_found_ia(self
, "apmdevif", &aaa
, apmprint
);
198 if (sc
->sc_apmdev
!= NULL
) {
200 callout_schedule(&sc
->sc_cyclic_poll
, CYCLIC_TIME
);
205 zapm_hook(void *v
, int type
, long id
, void *msg
)
207 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
212 if (type
!= CONFIG_HOOK_PMEVENT
)
215 if (CONFIG_HOOK_VALUEP(msg
))
218 message
= *(int *)msg
;
223 case CONFIG_HOOK_PMEVENT_STANDBYREQ
:
224 if (sc
->power_state
!= APM_SYS_STANDBY
) {
225 sc
->events
|= (1 << APM_USER_STANDBY_REQ
);
227 sc
->events
|= (1 << APM_NORMAL_RESUME
);
230 case CONFIG_HOOK_PMEVENT_SUSPENDREQ
:
231 if (sc
->power_state
!= APM_SYS_SUSPEND
) {
232 DPRINTF(("zapm: suspend request\n"));
233 sc
->events
|= (1 << APM_USER_SUSPEND_REQ
);
235 sc
->events
|= (1 << APM_NORMAL_RESUME
);
238 case CONFIG_HOOK_PMEVENT_BATTERY
:
240 case CONFIG_HOOK_BATT_CRITICAL
:
241 DPRINTF(("zapm: battery state critical\n"));
242 charge
= sc
->battery_state
& APM_BATT_FLAG_CHARGING
;
243 sc
->battery_state
= APM_BATT_FLAG_CRITICAL
;
244 sc
->battery_state
|= charge
;
245 sc
->battery_life
= 0;
247 case CONFIG_HOOK_BATT_LOW
:
248 DPRINTF(("zapm: battery state low\n"));
249 charge
= sc
->battery_state
& APM_BATT_FLAG_CHARGING
;
250 sc
->battery_state
= APM_BATT_FLAG_LOW
;
251 sc
->battery_state
|= charge
;
253 case CONFIG_HOOK_BATT_HIGH
:
254 DPRINTF(("zapm: battery state high\n"));
255 charge
= sc
->battery_state
& APM_BATT_FLAG_CHARGING
;
256 sc
->battery_state
= APM_BATT_FLAG_HIGH
;
257 sc
->battery_state
|= charge
;
259 case CONFIG_HOOK_BATT_10P
:
260 DPRINTF(("zapm: battery life 10%%\n"));
261 sc
->battery_life
= 10;
263 case CONFIG_HOOK_BATT_20P
:
264 DPRINTF(("zapm: battery life 20%%\n"));
265 sc
->battery_life
= 20;
267 case CONFIG_HOOK_BATT_30P
:
268 DPRINTF(("zapm: battery life 30%%\n"));
269 sc
->battery_life
= 30;
271 case CONFIG_HOOK_BATT_40P
:
272 DPRINTF(("zapm: battery life 40%%\n"));
273 sc
->battery_life
= 40;
275 case CONFIG_HOOK_BATT_50P
:
276 DPRINTF(("zapm: battery life 50%%\n"));
277 sc
->battery_life
= 50;
279 case CONFIG_HOOK_BATT_60P
:
280 DPRINTF(("zapm: battery life 60%%\n"));
281 sc
->battery_life
= 60;
283 case CONFIG_HOOK_BATT_70P
:
284 DPRINTF(("zapm: battery life 70%%\n"));
285 sc
->battery_life
= 70;
287 case CONFIG_HOOK_BATT_80P
:
288 DPRINTF(("zapm: battery life 80%%\n"));
289 sc
->battery_life
= 80;
291 case CONFIG_HOOK_BATT_90P
:
292 DPRINTF(("zapm: battery life 90%%\n"));
293 sc
->battery_life
= 90;
295 case CONFIG_HOOK_BATT_100P
:
296 DPRINTF(("zapm: battery life 100%%\n"));
297 sc
->battery_life
= 100;
299 case CONFIG_HOOK_BATT_UNKNOWN
:
300 DPRINTF(("zapm: battery state unknown\n"));
301 sc
->battery_state
= APM_BATT_FLAG_UNKNOWN
;
302 sc
->battery_life
= APM_BATT_LIFE_UNKNOWN
;
304 case CONFIG_HOOK_BATT_NO_SYSTEM_BATTERY
:
305 DPRINTF(("zapm: battery state no system battery?\n"));
306 sc
->battery_state
= APM_BATT_FLAG_NO_SYSTEM_BATTERY
;
307 sc
->battery_life
= APM_BATT_LIFE_UNKNOWN
;
311 case CONFIG_HOOK_PMEVENT_AC
:
313 case CONFIG_HOOK_AC_OFF
:
314 DPRINTF(("zapm: ac not connected\n"));
315 sc
->battery_state
&= ~APM_BATT_FLAG_CHARGING
;
316 sc
->ac_state
= APM_AC_OFF
;
318 case CONFIG_HOOK_AC_ON_CHARGE
:
319 DPRINTF(("zapm: charging\n"));
320 sc
->battery_state
|= APM_BATT_FLAG_CHARGING
;
321 sc
->ac_state
= APM_AC_ON
;
323 case CONFIG_HOOK_AC_ON_NOCHARGE
:
324 DPRINTF(("zapm: ac connected\n"));
325 sc
->battery_state
&= ~APM_BATT_FLAG_CHARGING
;
326 sc
->ac_state
= APM_AC_ON
;
328 case CONFIG_HOOK_AC_UNKNOWN
:
329 sc
->ac_state
= APM_AC_UNKNOWN
;
341 zapm_disconnect(void *v
)
344 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
349 zapm_enable(void *v
, int onoff
)
352 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
357 zapm_set_powstate(void *v
, u_int devid
, u_int powstat
)
359 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
361 if (devid
!= APM_DEV_ALLDEVS
)
362 return APM_ERR_UNRECOG_DEV
;
366 DPRINTF(("zapm: set power state READY\n"));
367 sc
->power_state
= APM_SYS_READY
;
369 case APM_SYS_STANDBY
:
370 DPRINTF(("zapm: set power state STANDBY\n"));
372 DPRINTF(("zapm: resume\n"));
374 case APM_SYS_SUSPEND
:
375 DPRINTF(("zapm: set power state SUSPEND...\n"));
377 DPRINTF(("zapm: resume\n"));
380 DPRINTF(("zapm: set power state OFF\n"));
381 sc
->power_state
= APM_SYS_OFF
;
383 case APM_LASTREQ_INPROG
:
384 /*DPRINTF(("zapm: set power state INPROG\n"));*/
386 case APM_LASTREQ_REJECTED
:
387 DPRINTF(("zapm: set power state REJECTED\n"));
395 zapm_get_powstat(void *v
, u_int batteryid
, struct apm_power_info
*pinfo
)
397 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
400 if (config_hook_call(CONFIG_HOOK_GET
,
401 CONFIG_HOOK_ACADAPTER
, &val
) != -1)
402 pinfo
->ac_state
= val
;
404 pinfo
->ac_state
= sc
->ac_state
;
405 DPRINTF(("zapm: pinfo->ac_state: %d\n", pinfo
->ac_state
));
407 if (config_hook_call(CONFIG_HOOK_GET
,
408 CONFIG_HOOK_CHARGE
, &val
) != -1)
409 pinfo
->battery_state
= val
;
411 DPRINTF(("zapm: sc->battery_state: %#x\n", sc
->battery_state
));
412 if (sc
->battery_state
& APM_BATT_FLAG_CHARGING
)
413 pinfo
->battery_flags
= APM_BATT_FLAG_CHARGING
;
414 else if (sc
->battery_state
& APM_BATT_FLAG_CRITICAL
)
415 pinfo
->battery_flags
= APM_BATT_FLAG_CRITICAL
;
416 else if (sc
->battery_state
& APM_BATT_FLAG_LOW
)
417 pinfo
->battery_flags
= APM_BATT_FLAG_LOW
;
418 else if (sc
->battery_state
& APM_BATT_FLAG_HIGH
)
419 pinfo
->battery_flags
= APM_BATT_FLAG_HIGH
;
421 pinfo
->battery_flags
= APM_BATT_FLAG_UNKNOWN
;
423 DPRINTF(("zapm: pinfo->battery_flags: %#x\n", pinfo
->battery_flags
));
425 if (config_hook_call(CONFIG_HOOK_GET
,
426 CONFIG_HOOK_BATTERYVAL
, &val
) != -1)
427 pinfo
->battery_life
= val
;
429 pinfo
->battery_life
= sc
->battery_life
;
430 DPRINTF(("zapm: pinfo->battery_life: %d\n", pinfo
->battery_life
));
436 zapm_get_event(void *v
, u_int
*event_type
, u_int
*event_info
)
438 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
443 for (ev
= APM_STANDBY_REQ
; ev
<= APM_CAP_CHANGE
; ev
++) {
444 if (sc
->events
& (1 << ev
)) {
445 sc
->events
&= ~(1 << ev
);
447 if (*event_type
== APM_NORMAL_RESUME
||
448 *event_type
== APM_CRIT_RESUME
) {
449 /* pccard power off in the suspend state */
451 sc
->power_state
= APM_SYS_READY
;
462 return APM_ERR_NOEVENTS
;
466 zapm_cpu_busy(void *v
)
469 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
474 zapm_cpu_idle(void *v
)
477 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
482 zapm_get_capabilities(void *v
, u_int
*numbatts
, u_int
*capflags
)
485 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
489 *capflags
= 0 /* | APM_GLOBAL_STANDBY | APM_GLOBAL_SUSPEND */;
492 /*-----------------------------------------------------------------------------
495 /* MAX1111 command word */
496 #define MAXCTRL_PD0 (1<<0)
497 #define MAXCTRL_PD1 (1<<1)
498 #define MAXCTRL_SGL (1<<2)
499 #define MAXCTRL_UNI (1<<3)
500 #define MAXCTRL_SEL_SHIFT 4
501 #define MAXCTRL_STR (1<<7)
503 /* MAX1111 ADC channels */
509 * Battery-specific information
511 struct battery_threshold
{
517 struct battery_info
{
518 const struct battery_threshold
*bi_thres
;
521 static const struct battery_threshold zaurus_battery_life_c3000
[] = {
522 { 100, 212, CONFIG_HOOK_BATT_HIGH
},
523 { 98, 212, CONFIG_HOOK_BATT_HIGH
},
524 { 95, 211, CONFIG_HOOK_BATT_HIGH
},
525 { 93, 210, CONFIG_HOOK_BATT_HIGH
},
526 { 90, 209, CONFIG_HOOK_BATT_HIGH
},
527 { 88, 208, CONFIG_HOOK_BATT_HIGH
},
528 { 85, 207, CONFIG_HOOK_BATT_HIGH
},
529 { 83, 206, CONFIG_HOOK_BATT_HIGH
},
530 { 80, 205, CONFIG_HOOK_BATT_HIGH
},
531 { 78, 204, CONFIG_HOOK_BATT_HIGH
},
532 { 75, 203, CONFIG_HOOK_BATT_HIGH
},
533 { 73, 202, CONFIG_HOOK_BATT_HIGH
},
534 { 70, 201, CONFIG_HOOK_BATT_HIGH
},
535 { 68, 200, CONFIG_HOOK_BATT_HIGH
},
536 { 65, 199, CONFIG_HOOK_BATT_HIGH
},
537 { 63, 198, CONFIG_HOOK_BATT_HIGH
},
538 { 60, 197, CONFIG_HOOK_BATT_HIGH
},
539 { 58, 196, CONFIG_HOOK_BATT_HIGH
},
540 { 55, 195, CONFIG_HOOK_BATT_HIGH
},
541 { 53, 194, CONFIG_HOOK_BATT_HIGH
},
542 { 50, 193, CONFIG_HOOK_BATT_HIGH
},
543 { 48, 192, CONFIG_HOOK_BATT_HIGH
},
544 { 45, 192, CONFIG_HOOK_BATT_HIGH
},
545 { 43, 191, CONFIG_HOOK_BATT_HIGH
},
546 { 40, 191, CONFIG_HOOK_BATT_HIGH
},
547 { 38, 190, CONFIG_HOOK_BATT_HIGH
},
548 { 35, 190, CONFIG_HOOK_BATT_HIGH
},
549 { 33, 189, CONFIG_HOOK_BATT_HIGH
},
550 { 30, 188, CONFIG_HOOK_BATT_HIGH
},
551 { 28, 187, CONFIG_HOOK_BATT_LOW
},
552 { 25, 186, CONFIG_HOOK_BATT_LOW
},
553 { 23, 185, CONFIG_HOOK_BATT_LOW
},
554 { 20, 184, CONFIG_HOOK_BATT_LOW
},
555 { 18, 183, CONFIG_HOOK_BATT_LOW
},
556 { 15, 182, CONFIG_HOOK_BATT_LOW
},
557 { 13, 181, CONFIG_HOOK_BATT_LOW
},
558 { 10, 180, CONFIG_HOOK_BATT_LOW
},
559 { 8, 179, CONFIG_HOOK_BATT_LOW
},
560 { 5, 178, CONFIG_HOOK_BATT_LOW
},
561 { 0, 0, CONFIG_HOOK_BATT_CRITICAL
}
564 static const struct battery_info zaurus_battery_c3000
= {
565 zaurus_battery_life_c3000
568 static const struct battery_info
*zaurus_main_battery
= &zaurus_battery_c3000
;
570 /* Restart charging this many times before accepting BATT_FULL. */
571 #define MIN_BATT_FULL 2
573 /* Discharge 100 ms before reading the voltage if AC is connected. */
574 #define DISCHARGE_TIMEOUT (hz / 10)
576 /* Check battery voltage and "kick charging" every minute. */
577 static const struct timeval zapm_battchkrate
= { 60, 0 };
579 static int zapm_get_ac_state(struct zapm_softc
*);
580 static int zapm_get_battery_compartment_state(struct zapm_softc
*);
581 static int zapm_get_charge_complete_state(struct zapm_softc
*);
582 static void zapm_set_charging(struct zapm_softc
*, int);
583 static int zapm_charge_complete(struct zapm_softc
*);
584 static int max1111_adc_value_avg(int chan
, int pause
);
585 static int zapm_get_battery_volt(void);
586 static int zapm_battery_state(int volt
);
587 static int zapm_battery_life(int volt
);
610 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
614 callout_schedule(&sc
->sc_cyclic_poll
, CYCLIC_TIME
);
625 zapm_get_ac_state(struct zapm_softc
*sc
)
628 if (!pxa2x0_gpio_get_bit(sc
->sc_ac_detect_pin
))
634 zapm_get_battery_compartment_state(struct zapm_softc
*sc
)
637 return pxa2x0_gpio_get_bit(sc
->sc_batt_cover_pin
);
641 zapm_get_charge_complete_state(struct zapm_softc
*sc
)
644 return pxa2x0_gpio_get_bit(sc
->sc_charge_comp_pin
);
648 zapm_set_charging(struct zapm_softc
*sc
, int enable
)
651 scoop_discharge_battery(0);
652 scoop_charge_battery(enable
, 0);
653 scoop_led_set(SCOOP_LED_ORANGE
, enable
);
657 * Return non-zero if the charge complete signal indicates that the
658 * battery is fully charged. Restart charging to clear this signal.
661 zapm_charge_complete(struct zapm_softc
*sc
)
664 if (sc
->charging
&& sc
->battery_full_cnt
< MIN_BATT_FULL
) {
665 if (zapm_get_charge_complete_state(sc
)) {
666 sc
->battery_full_cnt
++;
667 if (sc
->battery_full_cnt
< MIN_BATT_FULL
) {
668 DPRINTF(("battery almost full\n"));
669 zapm_set_charging(sc
, 0);
671 zapm_set_charging(sc
, 1);
673 } else if (sc
->battery_full_cnt
> 0) {
675 sc
->battery_full_cnt
= 0;
676 zapm_set_charging(sc
, 0);
678 zapm_set_charging(sc
, 1);
682 return (sc
->battery_full_cnt
>= MIN_BATT_FULL
);
686 max1111_adc_value(int chan
)
689 return ((int)zssp_ic_send(ZSSP_IC_MAX1111
, MAXCTRL_PD0
|
690 MAXCTRL_PD1
| MAXCTRL_SGL
| MAXCTRL_UNI
|
691 (chan
<< MAXCTRL_SEL_SHIFT
) | MAXCTRL_STR
));
696 max1111_adc_value_avg(int chan
, int pause
)
703 DPRINTF(("max1111_adc_value_avg: chan = %d, pause = %d\n",
706 for (i
= 0; i
< 5; i
++) {
707 val
[i
] = max1111_adc_value(chan
);
710 DPRINTF(("max1111_adc_value_avg: chan[%d] = %d\n", i
, val
[i
]));
716 for (i
= 1; i
< 5; i
++) {
726 for (i
= 3; i
>= 0; i
--) {
733 DPRINTF(("max1111_adc_value_avg: minv = %d, maxv = %d\n", minv
, maxv
));
735 for (i
= 0; i
< 5; i
++) {
736 if (i
== minv
|| i
== maxv
)
741 DPRINTF(("max1111_adc_value_avg: sum = %d, sum / 3 = %d\n",
748 zapm_get_battery_volt(void)
751 return max1111_adc_value_avg(BATT_AD
, 10);
755 zapm_battery_state(int volt
)
757 const struct battery_threshold
*bthr
;
760 bthr
= zaurus_main_battery
->bi_thres
;
762 for (i
= 0; bthr
[i
].value
> 0; i
++)
763 if (bthr
[i
].value
<= volt
)
766 return bthr
[i
].state
;
770 zapm_battery_life(int volt
)
772 const struct battery_threshold
*bthr
;
775 bthr
= zaurus_main_battery
->bi_thres
;
777 for (i
= 0; bthr
[i
].value
> 0; i
++)
778 if (bthr
[i
].value
<= volt
)
782 return bthr
[0].percent
;
784 return (bthr
[i
].percent
+
785 ((volt
- bthr
[i
].value
) * 100) /
786 (bthr
[i
-1].value
- bthr
[i
].value
) *
787 (bthr
[i
-1].percent
- bthr
[i
].percent
) / 100);
791 * Poll power-management related GPIO inputs, update battery life
792 * in softc, and/or control battery charging.
795 zapm_poll1(void *v
, int do_suspend
)
797 struct zapm_softc
*sc
= (struct zapm_softc
*)v
;
803 if (!mutex_tryenter(&sc
->sc_mtx
))
806 ac_state
= zapm_get_ac_state(sc
);
807 bc_lock
= zapm_get_battery_compartment_state(sc
);
809 /* Stop discharging. */
810 if (sc
->discharging
) {
813 volt
= zapm_get_battery_volt();
814 DPRINTF(("zapm_poll: discharge off volt %d\n", volt
));
816 charging
= sc
->battery_state
& APM_BATT_FLAG_CHARGING
;
817 volt
= sc
->battery_volt
;
820 /* Start or stop charging as necessary. */
821 if (ac_state
&& bc_lock
) {
822 int charge_completed
= zapm_charge_complete(sc
);
824 if (charge_completed
) {
825 DPRINTF(("zapm_poll: battery is full\n"));
827 zapm_set_charging(sc
, 0);
829 } else if (!charge_completed
) {
830 charging
= APM_BATT_FLAG_CHARGING
;
831 volt
= zapm_get_battery_volt();
832 zapm_set_charging(sc
, 1);
833 DPRINTF(("zapm_poll: start charging volt %d\n", volt
));
838 zapm_set_charging(sc
, 0);
839 timerclear(&sc
->sc_lastbattchk
);
840 DPRINTF(("zapm_poll: stop charging\n"));
842 sc
->battery_full_cnt
= 0;
846 * Restart charging once in a while. Discharge a few milliseconds
847 * before updating the voltage in our softc if A/C is connected.
849 if (bc_lock
&& ratecheck(&sc
->sc_lastbattchk
, &zapm_battchkrate
)) {
850 if (do_suspend
&& sc
->suspended
) {
853 DPRINTF(("zapm_poll: suspended %lu %lu\n",
854 sc
->lastbattchk
.tv_sec
,
855 pxa2x0_rtc_getsecs()));
857 zapm_set_charging(sc
, 0);
859 zapm_set_charging(sc
, 1);
860 pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() +
861 zapm_battchkrate
.tv_sec
+ 1);
864 } else if (ac_state
&& sc
->battery_full_cnt
== 0) {
865 DPRINTF(("zapm_poll: discharge on\n"));
867 zapm_set_charging(sc
, 0);
869 scoop_discharge_battery(1);
870 callout_schedule(&sc
->sc_discharge_poll
,
872 } else if (!ac_state
) {
873 volt
= zapm_get_battery_volt();
874 DPRINTF(("zapm_poll: volt %d\n", volt
));
878 /* Update the cached power state in our softc. */
879 if ((ac_state
!= sc
->ac_state
)
880 || (charging
!= (sc
->battery_state
& APM_BATT_FLAG_CHARGING
))) {
881 config_hook_call(CONFIG_HOOK_PMEVENT
,
882 CONFIG_HOOK_PMEVENT_AC
,
883 (void *)((ac_state
== APM_AC_OFF
)
885 : (charging
? CONFIG_HOOK_AC_ON_CHARGE
886 : CONFIG_HOOK_AC_ON_NOCHARGE
)));
888 if (volt
!= sc
->battery_volt
) {
889 sc
->battery_volt
= volt
;
890 sc
->battery_life
= zapm_battery_life(volt
);
891 config_hook_call(CONFIG_HOOK_PMEVENT
,
892 CONFIG_HOOK_PMEVENT_BATTERY
,
893 (void *)zapm_battery_state(volt
));
896 mutex_exit(&sc
->sc_mtx
);