summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpi
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2000-09-14 23:29:37 +0000
committeriwasaki <iwasaki@FreeBSD.org>2000-09-14 23:29:37 +0000
commit9a638b9d568eed5d66f28bd4873fd23fb10ec271 (patch)
tree787a95240edba67fe55891d615c83772f0dc0254 /sys/dev/acpi
parent48aa25a6f65fca2b6b8f868f95c262cc0cc99b73 (diff)
downloadFreeBSD-src-9a638b9d568eed5d66f28bd4873fd23fb10ec271.zip
FreeBSD-src-9a638b9d568eed5d66f28bd4873fd23fb10ec271.tar.gz
Add acpi_send_pm_event() to inform all devices that the system is
going to sleep and back from sleep. Also re-enabling some acpi registers on wakeup.
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r--sys/dev/acpi/acpi.c60
-rw-r--r--sys/dev/acpi/acpi.h6
2 files changed, 63 insertions, 3 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index 0ebbf83..a8b84a3 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -36,6 +36,9 @@
#include <sys/conf.h>
#include <sys/sysctl.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
#include <sys/eventhandler.h> /* for EVENTHANDLER_REGISTER */
#include <sys/reboot.h> /* for RB_POWEROFF */
#include <machine/clock.h> /* for DELAY */
@@ -153,6 +156,7 @@ static void acpi_enable_events(acpi_softc_t *sc);
/* New-bus dependent code */
static acpi_softc_t *acpi_get_softc(dev_t dev);
+static int acpi_send_pm_event(acpi_softc_t *sc, u_int8_t state);
static void acpi_identify(driver_t *driver, device_t parent);
static int acpi_probe(device_t dev);
static int acpi_attach(device_t dev);
@@ -374,6 +378,7 @@ acpi_enable_disable(acpi_softc_t *sc, boolean_t enable)
}
bus_space_write_1(bst, bsh, 0, val);
+ sc->enabled = enable;
ACPI_DEBUGPRINT("acpi_enable_disable(%d) = (%x)\n", enable, val);
}
@@ -680,6 +685,7 @@ acpi_handle_dsdt(acpi_softc_t *sc)
}
/* get sleeping type values from ACPI namespace */
+ sc->system_state = ACPI_S_STATE_S0;
sc->system_state_initialized = 1;
for (i = ACPI_S_STATE_S0; i <= ACPI_S_STATE_S5; i++) {
ssp.mode[i].slp_typ_a = ACPI_UNSUPPORTSLPTYP;
@@ -904,6 +910,13 @@ acpi_set_sleeping_state(acpi_softc_t *sc, u_int8_t state)
}
if (state < ACPI_S_STATE_S5) {
+ /* inform all devices that we are going to sleep. */
+ if (acpi_send_pm_event(sc, state) != 0) {
+ /* if failure, 'wakeup' the system again */
+ acpi_send_pm_event(sc, ACPI_S_STATE_S0);
+ return;
+ }
+
/* Prepare to sleep */
acpi_execute_pts(sc, state);
@@ -912,6 +925,8 @@ acpi_set_sleeping_state(acpi_softc_t *sc, u_int8_t state)
if (acpi_debug) {
acpi_powerres_debug(sc);
}
+
+ sc->system_state = state;
}
/*
@@ -931,11 +946,14 @@ acpi_set_sleeping_state(acpi_softc_t *sc, u_int8_t state)
}
if (state < ACPI_S_STATE_S5) {
- acpi_execute_wak(sc, state);
acpi_powerres_set_sleeping_state(sc, 0);
if (acpi_debug) {
acpi_powerres_debug(sc);
}
+ acpi_execute_wak(sc, state);
+ acpi_send_pm_event(sc, ACPI_S_STATE_S0);
+
+ sc->system_state = ACPI_S_STATE_S0;
}
}
@@ -1233,6 +1251,31 @@ acpi_get_softc(dev_t dev)
return (devclass_get_softc(acpi_devclass, minor(dev)));
}
+static int
+acpi_send_pm_event(acpi_softc_t *sc, u_int8_t state)
+{
+ int error;
+
+ error = 0;
+ switch (state) {
+ case ACPI_S_STATE_S0:
+ if (sc->system_state != ACPI_S_STATE_S0) {
+ DEVICE_RESUME(root_bus);
+ }
+ break;
+ case ACPI_S_STATE_S1:
+ case ACPI_S_STATE_S2:
+ case ACPI_S_STATE_S3:
+ case ACPI_S_STATE_S4:
+ error = DEVICE_SUSPEND(root_bus);
+ break;
+ default:
+ break;
+ }
+
+ return (error);
+}
+
static void
acpi_identify(driver_t *driver, device_t parent)
{
@@ -1342,11 +1385,26 @@ acpi_attach(device_t dev)
return (0);
}
+static int
+acpi_resume(device_t dev)
+{
+ acpi_softc_t *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->enabled) {
+ /* re-enable on wakeup */
+ acpi_enable_disable(sc, 1);
+ acpi_enable_events(sc);
+ }
+ return (0);
+}
+
static device_method_t acpi_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, acpi_identify),
DEVMETHOD(device_probe, acpi_probe),
DEVMETHOD(device_attach, acpi_attach),
+ DEVMETHOD(device_resume, acpi_resume),
{0, 0}
};
diff --git a/sys/dev/acpi/acpi.h b/sys/dev/acpi/acpi.h
index 4e1887b..5c4cb2e 100644
--- a/sys/dev/acpi/acpi.h
+++ b/sys/dev/acpi/acpi.h
@@ -53,7 +53,7 @@ struct acpi_powerres_info {
#define ACPI_POWER_RESOURCE_ON 1
#define ACPI_POWER_RESOURCE_OFF 0
u_int8_t state; /* OFF or ON */
-#define ACPI_PR_MAX 3
+#define ACPI_PR_MAX 3 /* _PR[0-2] */
LIST_HEAD(, acpi_powerres_device_ref) reflist[ACPI_PR_MAX];
};
@@ -64,8 +64,10 @@ typedef struct acpi_softc {
struct FACPbody *facp_body;
struct ACPIsdt *dsdt;
struct FACS *facs;
+ int system_state;
int system_state_initialized;
int broken_wakeuplogic;
+ int enabled;
struct acpi_system_state_package system_state_package;
LIST_HEAD(, acpi_powerres_info) acpi_powerres_inflist;
LIST_HEAD(, acpi_powerres_device) acpi_powerres_devlist;
@@ -84,4 +86,4 @@ void acpi_set_powerres_state(acpi_softc_t *, struct aml_name *,
u_int8_t);
void acpi_powerres_set_sleeping_state(acpi_softc_t *, u_int8_t);
-#endif /* _DEV_ACPI_ACPI_H_ */
+#endif /* !_DEV_ACPI_ACPI_H_ */
OpenPOWER on IntegriCloud