diff options
author | Uwe Stuehler <uwe@cvs.openbsd.org> | 2005-04-13 05:40:08 +0000 |
---|---|---|
committer | Uwe Stuehler <uwe@cvs.openbsd.org> | 2005-04-13 05:40:08 +0000 |
commit | 213bb9eacc71ebebb78c9b0af1819a52088929d1 (patch) | |
tree | 52fa9edc8f7f1a95ccdfb4f10338adfb0901249c /sys/arch | |
parent | ff33f430a373c5630d1d0829e64021f3d8b58251 (diff) |
Call special suspend and resume hooks. The latter can cancel a resume.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_apm.c | 65 | ||||
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_apm.h | 5 |
2 files changed, 51 insertions, 19 deletions
diff --git a/sys/arch/arm/xscale/pxa2x0_apm.c b/sys/arch/arm/xscale/pxa2x0_apm.c index 5149ad369e5..ced5b04deb2 100644 --- a/sys/arch/arm/xscale/pxa2x0_apm.c +++ b/sys/arch/arm/xscale/pxa2x0_apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_apm.c,v 1.12 2005/04/11 03:07:09 uwe Exp $ */ +/* $OpenBSD: pxa2x0_apm.c,v 1.13 2005/04/13 05:40:07 uwe Exp $ */ /*- * Copyright (c) 2001 Alexander Guy. All rights reserved. @@ -308,6 +308,11 @@ apm_suspend(struct pxa2x0_apm_softc *sc) if (cold) vfs_syncwait(0); + if (sc->sc_suspend == NULL) + pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1); + else + sc->sc_suspend(sc); + pxa2x0_apm_sleep(sc); } @@ -718,6 +723,7 @@ pxa2x0_wakeup_config(u_int wsrc, int enable) prer |= (1<<31); if (enable) { + sc->sc_wakeon |= wsrc; prer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PRER); pfer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, @@ -725,6 +731,7 @@ pxa2x0_wakeup_config(u_int wsrc, int enable) pkwr |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKWR); } else { + sc->sc_wakeon &= ~wsrc; prer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PRER) & ~prer; pfer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, @@ -733,19 +740,11 @@ pxa2x0_wakeup_config(u_int wsrc, int enable) POWMAN_PKWR) & ~pkwr; } + bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKWR, pkwr); bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PRER, prer); bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PFER, pfer); bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PWER, prer | pfer); - bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR, - 0xffffffff); - bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKWR, pkwr); - bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR, - 0xffffffff); - - /* XXX do that just before suspend. */ - pxa2x0_clkman_config(CKEN_KEY, - (wsrc & PXA2X0_WAKEUP_KEYNS_ALL) != 0); } u_int @@ -874,6 +873,13 @@ pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc) delay(500000); /* XXX */ } +suspend_again: + /* Clear wake-up status. */ + bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR, + 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR, + 0xffffffff); + scoop_check_mcr(); /* XXX control battery charging in sleep mode. */ @@ -883,8 +889,6 @@ pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc) /* XXX schedule RTC alarm to check the battery, or schedule XXX wake-up shortly before an already programmed alarm? */ - pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1); - pxa27x_run_mode(); #define MDREFR_LOW (MDREFR_C3000 | 0x00b) pxa27x_fastbus_run_mode(0, MDREFR_LOW); @@ -952,8 +956,15 @@ pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc) sd.sd_cken = bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN); - bus_space_write_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN, - CKEN_MEM | CKEN_KEY); + + /* + * Stop clocks to all units except to the memory controller, and + * to the keypad controller if it is enabled as a wake-up source. + */ + rv = CKEN_MEM; + if ((sc->sc_wakeon & PXA2X0_WAKEUP_KEYNS_ALL) != 0) + rv |= CKEN_KEY; + bus_space_write_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN, rv); /* Disable nRESET_OUT. */ rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR); @@ -1016,10 +1027,13 @@ pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc) pxa2x0_clkman_config(CKEN_SSP|CKEN_PWM0|CKEN_PWM1, 1); pxa2x0_clkman_config(CKEN_KEY, 0); +#if 1 /* Clear all GPIO interrupt sources. */ bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR0, 0xffffffff); bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR1, 0xffffffff); bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR2, 0xffffffff); +#endif + bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, sd.sd_gpdr0); bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, sd.sd_gpdr1); bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, sd.sd_gpdr2); @@ -1098,12 +1112,29 @@ pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc) delay(1); /* XXX is the delay long enough, and necessary at all? */ pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high); - bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PMCR, 0); - /* Change to 416Mhz turbo mode with fast-bus enabled. */ pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T, &pxa2x0_memcfg); + if (sc->sc_resume != NULL) { + /* Restore OS timers only to allow the use of delay(). */ + bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR1, sd.sd_osmr1); + bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR2, sd.sd_osmr2); + bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR3, sd.sd_osmr3); + bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSCR0, sd.sd_oscr0); + bus_space_write_4(sc->sc_iot, ost_ioh, OST_OIER, sd.sd_oier); + if (!sc->sc_resume(sc)) + goto suspend_again; + } + + /* + * Allow immediate entry into deep-sleep mode if power fails. + * Resume from immediate deep-sleep is not implemented yet. + */ + bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PMCR, 0); + + inittodr(0); + bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR0, sd.sd_osmr0); bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR1, sd.sd_osmr1); bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR2, sd.sd_osmr2); @@ -1111,8 +1142,6 @@ pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc) bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSCR0, sd.sd_oscr0); bus_space_write_4(sc->sc_iot, ost_ioh, OST_OIER, sd.sd_oier); - inittodr(0); - restore_interrupts(save); out: diff --git a/sys/arch/arm/xscale/pxa2x0_apm.h b/sys/arch/arm/xscale/pxa2x0_apm.h index a20d1d16d4a..7770c94e189 100644 --- a/sys/arch/arm/xscale/pxa2x0_apm.h +++ b/sys/arch/arm/xscale/pxa2x0_apm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_apm.h,v 1.6 2005/04/11 03:07:09 uwe Exp $ */ +/* $OpenBSD: pxa2x0_apm.h,v 1.7 2005/04/13 05:40:07 uwe Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> @@ -30,6 +30,7 @@ struct pxa2x0_apm_softc { struct lock sc_lock; struct klist sc_note; int sc_flags; + int sc_wakeon; /* enabled wakeup sources */ int sc_batt_life; bus_space_tag_t sc_iot; bus_space_handle_t sc_pm_ioh; @@ -37,6 +38,8 @@ struct pxa2x0_apm_softc { int (*sc_get_event)(struct pxa2x0_apm_softc *, u_int *); void (*sc_power_info)(struct pxa2x0_apm_softc *, struct apm_power_info *); + void (*sc_suspend)(struct pxa2x0_apm_softc *); + int (*sc_resume)(struct pxa2x0_apm_softc *); }; void pxa2x0_apm_attach_sub(struct pxa2x0_apm_softc *); |