diff options
author | Uwe Stuehler <uwe@cvs.openbsd.org> | 2007-03-29 18:42:39 +0000 |
---|---|---|
committer | Uwe Stuehler <uwe@cvs.openbsd.org> | 2007-03-29 18:42:39 +0000 |
commit | baa31b7505103721e06149694e3a0a0a6b726a75 (patch) | |
tree | 1e8e36dc507c5aee0c34c04ed2a52c394b9bf9f0 | |
parent | 39db385c566253b8b3e3fc4bf00808441f47b61c (diff) |
Add power hook to scoop(4), replacing the Zaurus-specific scoop_* calls in
pxa2x0_apm.c.
Set a flag to indicate that scoop is currently suspended. Test this flag
in scoop_timeout() (and maybe later in other places) to avoid manipulating
scoop registers while the driver is suspended. The scoop_checkdisk timeout
is intentionally not stopped, as it should be safe to have timeouts running
accross suspend/resume.
Put splhigh() in scoop_gpio_pin_write() to make changing the pin level an
atomic operation.
Result of prodding and diffs from Robert and Theo.
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_apm.c | 15 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_scoop.c | 53 |
2 files changed, 51 insertions, 17 deletions
diff --git a/sys/arch/arm/xscale/pxa2x0_apm.c b/sys/arch/arm/xscale/pxa2x0_apm.c index e8bb228480a..d38b571634e 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.27 2006/12/12 23:14:27 dim Exp $ */ +/* $OpenBSD: pxa2x0_apm.c,v 1.28 2007/03/29 18:42:38 uwe Exp $ */ /*- * Copyright (c) 2001 Alexander Guy. All rights reserved. @@ -235,11 +235,6 @@ void pxa27x_cpu_speed_low(void); void pxa27x_cpu_speed_91(void); void pxa27x_cpu_speed_208(void); -/* XXX */ -void scoop_check_mcr(void); -void scoop_suspend(void); -void scoop_resume(void); - void apm_power_print(struct pxa2x0_apm_softc *sc, struct apm_power_info *powerp) { @@ -905,8 +900,6 @@ suspend_again: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR, 0xffffffff); - scoop_check_mcr(); - /* XXX control battery charging in sleep mode. */ /* XXX schedule RTC alarm to check the battery, or schedule @@ -924,9 +917,6 @@ suspend_again: #endif pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh, PI2C_VOLTAGE_LOW); - scoop_check_mcr(); - scoop_suspend(); - sd.sd_gpdr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0); sd.sd_gpdr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1); sd.sd_gpdr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2); @@ -1124,9 +1114,6 @@ suspend_again: if ((read_icu(INTCTL_ICIP) & 0x1) != 0) bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR, 0x1); - scoop_check_mcr(); - scoop_resume(); - 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); diff --git a/sys/arch/zaurus/dev/zaurus_scoop.c b/sys/arch/zaurus/dev/zaurus_scoop.c index 795a36d53ce..71d50a29465 100644 --- a/sys/arch/zaurus/dev/zaurus_scoop.c +++ b/sys/arch/zaurus/dev/zaurus_scoop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: zaurus_scoop.c,v 1.15 2007/03/27 23:23:22 deraadt Exp $ */ +/* $OpenBSD: zaurus_scoop.c,v 1.16 2007/03/29 18:42:38 uwe Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> @@ -40,6 +40,8 @@ struct scoop_softc { bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; u_int16_t sc_gpwr; /* GPIO state before suspend */ + void *sc_powerhook; + int sc_suspended; }; int scoopmatch(struct device *, void *, void *); @@ -65,6 +67,7 @@ void scoop0_set_card_power(enum card, int); struct timeout scoop_checkdisk; void scoop_timeout(void *); +void scoop_power(int, void *); int scoopmatch(struct device *parent, void *match, void *aux) @@ -112,9 +115,15 @@ scoopattach(struct device *parent, struct device *self, void *aux) scoop_gpio_pin_write(sc, SCOOP0_AKIN_PULLUP, GPIO_PIN_LOW); } - timeout_set(&scoop_checkdisk, scoop_timeout, sc); + if (sc->sc_dev.dv_unit == 0) + timeout_set(&scoop_checkdisk, scoop_timeout, sc); printf(": PCMCIA/GPIO controller\n"); + + sc->sc_powerhook = powerhook_establish(scoop_power, sc); + if (sc->sc_powerhook == NULL) + panic("Unable to establish %s powerhook", + sc->sc_dev.dv_xname); } int @@ -132,10 +141,13 @@ scoop_gpio_pin_write(struct scoop_softc *sc, int pin, int level) { u_int16_t rv; u_int16_t bit = (1 << pin); + int s; + s = splhigh(); rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR); bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, level == GPIO_PIN_LOW ? (rv & ~bit) : (rv | bit)); + splx(s); } void @@ -358,6 +370,8 @@ scoop_suspend(void) struct scoop_softc *sc; u_int32_t rv; + scoop_check_mcr(); + if (scoop_cd.cd_ndevs > 0 && scoop_cd.cd_devs[0] != NULL) { sc = scoop_cd.cd_devs[0]; sc->sc_gpwr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, @@ -390,6 +404,8 @@ scoop_resume(void) { struct scoop_softc *sc; + scoop_check_mcr(); + if (scoop_cd.cd_ndevs > 0 && scoop_cd.cd_devs[0] != NULL) { sc = scoop_cd.cd_devs[0]; bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, @@ -407,6 +423,7 @@ void scoop_timeout(void *v) { extern struct disklist_head disklist; + struct scoop_softc *sc = v; static struct disk *dk; static int state = 0; @@ -418,7 +435,9 @@ scoop_timeout(void *v) break; } - if (dk) { + if (sc->sc_suspended) + state = -1; + else if (dk) { int newstate = (dk->dk_busy ? 1 : 0); if (newstate != state) { @@ -428,3 +447,31 @@ scoop_timeout(void *v) } timeout_add(&scoop_checkdisk, hz/25); } + +void +scoop_power(int why, void *arg) +{ + struct scoop_softc *sc = arg; + + switch (why) { + case PWR_STANDBY: + case PWR_SUSPEND: + /* + * Nothing should use the scoop from this point on. + * No timeouts, no interrupts (even though interrupts + * are still enabled). scoop_timeout() respects the + * sc_suspended flag. + */ + if (sc->sc_dev.dv_unit == 0) { + sc->sc_suspended = 1; + scoop_suspend(); + } + break; + case PWR_RESUME: + if (sc->sc_dev.dv_unit == 0) { + scoop_resume(); + sc->sc_suspended = 0; + } + break; + } +} |