summaryrefslogtreecommitdiff
path: root/sys/arch/zaurus/dev
diff options
context:
space:
mode:
authorUwe Stuehler <uwe@cvs.openbsd.org>2005-04-13 05:49:58 +0000
committerUwe Stuehler <uwe@cvs.openbsd.org>2005-04-13 05:49:58 +0000
commit5c1e37a35295e64d067f934c94ce0ab5ef9d387d (patch)
treed6195c2e671e23ceac8d3f9b32772bc11a9dd368 /sys/arch/zaurus/dev
parent213bb9eacc71ebebb78c9b0af1819a52088929d1 (diff)
Resume only if the lid is open and the power key pressed. Also fix
peridic discharging in zapm_poll().
Diffstat (limited to 'sys/arch/zaurus/dev')
-rw-r--r--sys/arch/zaurus/dev/zaurus_apm.c95
1 files changed, 83 insertions, 12 deletions
diff --git a/sys/arch/zaurus/dev/zaurus_apm.c b/sys/arch/zaurus/dev/zaurus_apm.c
index e9d76da3041..264d761ffe4 100644
--- a/sys/arch/zaurus/dev/zaurus_apm.c
+++ b/sys/arch/zaurus/dev/zaurus_apm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: zaurus_apm.c,v 1.5 2005/04/11 03:21:03 uwe Exp $ */
+/* $OpenBSD: zaurus_apm.c,v 1.6 2005/04/13 05:49:57 uwe Exp $ */
/*
* Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
@@ -28,6 +28,7 @@
#include <zaurus/dev/zaurus_scoopvar.h>
#include <zaurus/dev/zaurus_sspvar.h>
+void zssp_init(void); /* XXX */
#include <zaurus/dev/zaurus_apm.h>
@@ -41,6 +42,7 @@ struct zapm_softc {
struct pxa2x0_apm_softc sc;
struct timeout sc_poll;
struct timeval sc_lastbattchk;
+ int sc_suspended;
int sc_ac_on;
int sc_charging;
int sc_discharging;
@@ -140,6 +142,8 @@ int zapm_charge_complete(struct zapm_softc *);
void zapm_poll(void *);
int zapm_get_event(struct pxa2x0_apm_softc *, u_int *);
void zapm_power_info(struct pxa2x0_apm_softc *, struct apm_power_info *);
+void zapm_suspend(struct pxa2x0_apm_softc *);
+int zapm_resume(struct pxa2x0_apm_softc *);
int
@@ -162,8 +166,11 @@ apm_attach(struct device *parent, struct device *self, void *aux)
IPL_BIO, zapm_acintr, sc, "apm_ac");
#endif
+ sc->sc_event = APM_NOEVENT;
sc->sc.sc_get_event = zapm_get_event;
sc->sc.sc_power_info = zapm_power_info;
+ sc->sc.sc_suspend = zapm_suspend;
+ sc->sc.sc_resume = zapm_resume;
timeout_set(&sc->sc_poll, &zapm_poll, sc);
@@ -402,8 +409,10 @@ zapm_poll(void *v)
volt = zapm_batt_volt();
zapm_enable_charging(sc, 1);
DPRINTF(("zapm_poll: start charging volt %d\n", volt));
- } else if (ratecheck(&sc->sc_lastbattchk, &zapm_battchkrate)
- && !zapm_charge_complete(sc)) {
+ }
+
+ if (!sc->sc_suspended && sc->sc_batt_full == 0 &&
+ ratecheck(&sc->sc_lastbattchk, &zapm_battchkrate)) {
DPRINTF(("zapm_poll: discharge on\n"));
if (charging)
zapm_enable_charging(sc, 0);
@@ -418,7 +427,8 @@ zapm_poll(void *v)
zapm_enable_charging(sc, 0);
timerclear(&sc->sc_lastbattchk);
DPRINTF(("zapm_poll: stop charging\n"));
- } else if (ratecheck(&sc->sc_lastbattchk, &zapm_battchkrate)) {
+ } else if (!sc->sc_suspended &&
+ ratecheck(&sc->sc_lastbattchk, &zapm_battchkrate)) {
volt = zapm_batt_volt();
DPRINTF(("zapm_poll: volt %d\n", volt));
}
@@ -495,6 +505,68 @@ zapm_power_info(struct pxa2x0_apm_softc *pxa_sc, struct apm_power_info *power)
power->minutes_left = zapm_batt_minutes(power->battery_life);
}
+/*
+ * Called before suspending when all powerhooks are done.
+ */
+void
+zapm_suspend(struct pxa2x0_apm_softc *pxa_sc)
+{
+ struct zapm_softc *sc = (struct zapm_softc *)pxa_sc;
+
+ sc->sc_suspended = 1;
+ timeout_del(&sc->sc_poll);
+ zapm_poll(sc);
+
+ if (sc->sc_charging) {
+ zapm_enable_charging(sc, 0);
+ delay(15000);
+ zapm_enable_charging(sc, 1);
+ }
+
+ pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1);
+}
+
+/*
+ * Called after wake-up from suspend with interrupts still disabled,
+ * before any powerhooks are done.
+ */
+int
+zapm_resume(struct pxa2x0_apm_softc *pxa_sc)
+{
+ struct zapm_softc *sc = (struct zapm_softc *)pxa_sc;
+ int a, b;
+ u_int wsrc;
+ int wakeup = 0;
+
+ /* C3000 */
+ a = pxa2x0_gpio_get_bit(97) ? 1 : 0;
+ b = pxa2x0_gpio_get_bit(96) ? 2 : 0;
+
+ wsrc = pxa2x0_wakeup_status();
+
+ /* Resume only if the lid is not closed. */
+ if ((a | b) != 3 && (wsrc & PXA2X0_WAKEUP_POWERON) != 0) {
+ int timeout = 100; /* 10 ms */
+ /* C3000 */
+ while (timeout-- > 0 && pxa2x0_gpio_get_bit(95) != 0) {
+ if (timeout == 0) {
+ wakeup = 1;
+ break;
+ }
+ delay(100);
+ }
+ }
+
+ /* Initialize the SSP unit before using the MAX1111 again. */
+ zssp_init();
+
+ zapm_poll(sc);
+ if (wakeup)
+ sc->sc_suspended = 0;
+
+ return (wakeup);
+}
+
void
zapm_poweroff(void)
{
@@ -503,7 +575,8 @@ zapm_poweroff(void)
KASSERT(apm_cd.cd_ndevs > 0 && apm_cd.cd_devs[0] != NULL);
sc = apm_cd.cd_devs[0];
-#if 0
+ dopowerhooks(PWR_SUSPEND);
+
/* XXX enable charging during suspend */
/* XXX keep power LED state during suspend */
@@ -512,17 +585,15 @@ zapm_poweroff(void)
/* XXX scoop power down */
- pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1);
-
/* XXX set PGSRn and GPDRn */
-#endif
- dopowerhooks(PWR_SUSPEND);
+ pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1);
- /* Turn off the status LED to avoid blinking before restart. */
- scoop_led_set(SCOOP_LED_GREEN, 0);
+ do {
+ pxa2x0_apm_sleep(sc);
+ }
+ while (!zapm_resume(sc));
- pxa2x0_apm_sleep(sc);
zapm_restart();
/* NOTREACHED */