Index: j720kbd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcarm/dev/j720kbd.c,v
retrieving revision 1.3
diff -u -r1.3 j720kbd.c
--- j720kbd.c	27 Jun 2006 14:36:50 -0000	1.3
+++ j720kbd.c	25 Sep 2006 04:50:01 -0000
@@ -59,7 +59,6 @@
 #include <dev/hpc/hpckbdvar.h>
 
 #include <hpcarm/dev/j720sspvar.h>
-#include <hpcarm/dev/sed1356var.h>
 
 #ifdef DEBUG
 #define DPRINTF(arg)	printf arg
@@ -93,7 +92,6 @@
 static int	j720kbd_intr(void *);
 static int	j720kbd_poll(void *);
 static void	j720kbd_read(struct j720kbd_chip *, char *);
-static int	j720kbd_button_event(void *, int, long, void *);
 
 CFATTACH_DECL(j720kbd, sizeof(struct j720kbd_softc),
     j720kbd_match, j720kbd_attach, NULL, NULL);
@@ -132,11 +130,6 @@
 	/* Install interrupt handler. */
 	sa11x0_intr_establish(0, 0, 1, IPL_TTY, j720kbd_intr, sc);
 
-	/* Add config hook for light button event. */
-	config_hook(CONFIG_HOOK_BUTTONEVENT,
-		    CONFIG_HOOK_BUTTONEVENT_LIGHT,
-		    CONFIG_HOOK_SHARE, j720kbd_button_event, sc);
-
 	/* Attach hpckbd. */
 	haa.haa_ic = &sc->sc_chip->scc_if;
 	config_found(self, &haa, hpckbd_print);
@@ -253,16 +246,3 @@
 
 	DPRINTF(("j720kbd_read: error %x\n", data));
 }
-
-static int
-j720kbd_button_event(void *ctx, int type, long id, void *msg)
-{
-
-	if (type != CONFIG_HOOK_BUTTONEVENT ||
-	    id != CONFIG_HOOK_BUTTONEVENT_LIGHT)
-		return 0;
-
-	sed1356_toggle_lcdlight();
-
-	return 1;
-}
Index: j720pwr.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcarm/dev/j720pwr.c,v
retrieving revision 1.2
diff -u -r1.2 j720pwr.c
--- j720pwr.c	27 Jun 2006 14:36:50 -0000	1.2
+++ j720pwr.c	25 Sep 2006 04:50:02 -0000
@@ -72,11 +72,18 @@
 	struct device		sc_dev;
 
 	struct j720ssp_softc	*sc_ssp;
+
+	volatile int		sc_state;
+#define J720PWR_POWEROFF	0x01
+#define J720PWR_SLEEPING	0x02
 };
 
 static int	j720pwr_match(struct device *, struct cfdata *, void *);
 static void	j720pwr_attach(struct device *, struct device *, void *);
 
+static void	j720pwr_sleep(void *);
+static int	j720pwr_suspend_hook(void *, int, long, void *);
+static int	j720pwr_event_hook(void *, int, long, void *);
 static int	j720pwr_apm_getpower_hook(void *, int, long, void *);
 static int	j720pwr_get_battery(struct j720pwr_softc *);
 static int	j720pwr_get_ac_status(struct j720pwr_softc *);
@@ -120,10 +127,17 @@
 j720pwr_attach(struct device *parent, struct device *self, void *aux)
 {
 	struct j720pwr_softc *sc = (struct j720pwr_softc *)self;
+	extern void (*__sleep_func)(void *);
+	extern void *__sleep_ctx;
 
 	printf("\n");
 
 	sc->sc_ssp = (struct j720ssp_softc *)parent;
+	sc->sc_state = 0;
+
+	/* Register apm sleep function. */
+	__sleep_func = j720pwr_sleep;
+	__sleep_ctx = sc;
 
 	/* Battery status query hook. */
 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BATTERYVAL,
@@ -137,10 +151,94 @@
 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_ACADAPTER,
 		    CONFIG_HOOK_EXCLUSIVE, j720pwr_apm_getpower_hook, sc);
 
+	/* Suspend/resume button hook. */
+	config_hook(CONFIG_HOOK_BUTTONEVENT,
+		    CONFIG_HOOK_BUTTONEVENT_POWER,
+		    CONFIG_HOOK_SHARE, j720pwr_suspend_hook, sc);
+
+	/* Receive suspend/resume events. */
+	config_hook(CONFIG_HOOK_PMEVENT,
+		    CONFIG_HOOK_PMEVENT_HARDPOWER,
+		    CONFIG_HOOK_SHARE, j720pwr_event_hook, sc);
+
 	/* Attach hpcapm. */
 	config_found_ia(self, "hpcapmif", NULL, NULL);
 }
 
+static void
+j720pwr_sleep(void *ctx)
+{
+	struct j720pwr_softc *sc = ctx;
+	struct j720ssp_softc *ssp = sc->sc_ssp;
+	uint32_t oldfer;
+
+	/* Disable falling-edge detect on all GPIO ports, except keyboard. */
+	oldfer = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER);
+	bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, 1 << 0);
+
+	while (sc->sc_state & J720PWR_POWEROFF) {
+		/*
+		 * Just sleep here until the poweroff bit gets unset.
+		 * We need to wait here because when machine_sleep() returns
+		 * hpcapm(4) assumes that we are "resuming".
+		 */
+		(void)tsleep(&sc->sc_state, PWAIT, "j720slp", 0);
+	}
+
+	/* Restore previous FER value. */
+	bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, oldfer);
+}
+
+static int
+j720pwr_suspend_hook(void *ctx, int type, long id, void *msg)
+{
+	struct j720pwr_softc *sc = ctx;
+
+	if (type != CONFIG_HOOK_BUTTONEVENT ||
+	    id != CONFIG_HOOK_BUTTONEVENT_POWER)
+		return EINVAL;
+
+	if ((sc->sc_state & (J720PWR_POWEROFF | J720PWR_SLEEPING)) == 0) {
+		sc->sc_state |= J720PWR_POWEROFF;
+	} else if ((sc->sc_state & (J720PWR_POWEROFF | J720PWR_SLEEPING)) ==
+	    (J720PWR_POWEROFF | J720PWR_SLEEPING)) {
+		sc->sc_state &= ~J720PWR_POWEROFF;
+		wakeup(&sc->sc_state);
+	} else {
+		DPRINTF(("j720pwr_suspend_hook: busy\n"));
+		return EBUSY;
+	}
+
+	config_hook_call(CONFIG_HOOK_PMEVENT,
+		         CONFIG_HOOK_PMEVENT_SUSPENDREQ, NULL);
+
+	return 0;
+}
+
+static int
+j720pwr_event_hook(void *ctx, int type, long id, void *msg)
+{
+	struct j720pwr_softc *sc = ctx;
+	int event = (int)msg;
+
+	if (type != CONFIG_HOOK_PMEVENT ||
+	    id != CONFIG_HOOK_PMEVENT_HARDPOWER)
+		return EINVAL;
+
+	switch (event) {
+	case PWR_SUSPEND:
+		sc->sc_state |= (J720PWR_SLEEPING | J720PWR_POWEROFF);
+		break;
+	case PWR_RESUME:
+		sc->sc_state &= ~(J720PWR_SLEEPING | J720PWR_POWEROFF);
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return 0;
+}
+
 static int
 j720pwr_apm_getpower_hook(void *ctx, int type, long id, void *msg)
 {
