summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUwe Stuehler <uwe@cvs.openbsd.org>2007-03-29 18:42:39 +0000
committerUwe Stuehler <uwe@cvs.openbsd.org>2007-03-29 18:42:39 +0000
commitbaa31b7505103721e06149694e3a0a0a6b726a75 (patch)
tree1e8e36dc507c5aee0c34c04ed2a52c394b9bf9f0
parent39db385c566253b8b3e3fc4bf00808441f47b61c (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.c15
-rw-r--r--sys/arch/zaurus/dev/zaurus_scoop.c53
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;
+ }
+}