diff options
author | Paul Irofti <pirofti@cvs.openbsd.org> | 2010-08-31 10:24:47 +0000 |
---|---|---|
committer | Paul Irofti <pirofti@cvs.openbsd.org> | 2010-08-31 10:24:47 +0000 |
commit | 12ed26cb2111068191436c2c2d5ea96bfabc55c3 (patch) | |
tree | 22f3b4be2aefaef7b505f1c7d6b6335e6617c559 /sys/arch/loongson/dev/kb3310.c | |
parent | fac9264a5a14dde04909fa5d6f9d716e54ff2f9c (diff) |
WIP suspend/resume support for loongson lemote. Okay miod@.
Diffstat (limited to 'sys/arch/loongson/dev/kb3310.c')
-rw-r--r-- | sys/arch/loongson/dev/kb3310.c | 105 |
1 files changed, 104 insertions, 1 deletions
diff --git a/sys/arch/loongson/dev/kb3310.c b/sys/arch/loongson/dev/kb3310.c index ab9a4634b90..2cf28c8d6d7 100644 --- a/sys/arch/loongson/dev/kb3310.c +++ b/sys/arch/loongson/dev/kb3310.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kb3310.c,v 1.11 2010/07/31 16:04:46 miod Exp $ */ +/* $OpenBSD: kb3310.c,v 1.12 2010/08/31 10:24:46 pirofti Exp $ */ /* * Copyright (c) 2010 Otto Moerbeek <otto@drijf.net> * @@ -28,6 +28,10 @@ #include <machine/bus.h> #include <dev/isa/isavar.h> +#include <loongson/dev/bonitoreg.h> +#include <loongson/dev/kb3310var.h> +#include <loongson/dev/glxreg.h> + #include "apm.h" #include "pckbd.h" #include "hidkbd.h" @@ -42,6 +46,12 @@ struct cfdriver ykbec_cd = { NULL, "ykbec", DV_DULL, }; +#ifdef KB3310_DEBUG +#define DPRINTF(x) printf x +#else +#define DPRINTF(x) +#endif + #define IO_YKBEC 0x381 #define IO_YKBECSIZE 0x3 @@ -81,6 +91,12 @@ struct ykbec_softc { #endif }; +static struct ykbec_softc *ykbec_sc; +static int ykbec_chip_config; +static int ykbec_apmspl; + +extern void loongson_set_isa_imr(uint); + int ykbec_match(struct device *, void *, void *); void ykbec_attach(struct device *, struct device *, void *); @@ -187,6 +203,7 @@ ykbec_attach(struct device *parent, struct device *self, void *aux) hidkbd_hookup_bell(ykbec_bell, sc); #endif #endif + ykbec_sc = sc; } void @@ -273,6 +290,28 @@ ykbec_read16(struct ykbec_softc *mcsc, u_int reg) #define REG_BEEP_CONTROL 0xf4d0 #define BEEP_ENABLE (1<<0) +#define REG_PMUCFG 0xff0c +#define PMUCFG_STOP_MODE (1<<7) +#define PMUCFG_IDLE_MODE (1<<6) +#define PMUCFG_LPC_WAKEUP (1<<5) +#define PMUCFG_RESET_8051 (1<<4) +#define PMUCFG_SCI_WAKEUP (1<<3) +#define PMUCFG_WDT_WAKEUP (1<<2) +#define PMUCFG_GPWU_WAKEUP (1<<1) +#define PMUCFG_IRQ_IDLE (1<<0) + +#define REG_USB0 0xf461 +#define REG_USB1 0xf462 +#define REG_USB2 0xf463 +#define USB_FLAG_ON 1 +#define USB_FLAG_OFF 0 + +#define REG_FAN_CONTROL 0xf4d2 +#define REG_FAN_ON 1 +#define REG_FAN_OFF 0 + +#define YKBEC_SCI_IRQ 0xa + #ifdef DEBUG void ykbec_print_bat_info(struct ykbec_softc *sc) @@ -400,6 +439,70 @@ ykbec_apminfo(struct apm_power_info *info) bcopy(&ykbec_apmdata, info, sizeof(struct apm_power_info)); return 0; } + +int +ykbec_suspend() +{ + struct ykbec_softc *sc = ykbec_sc; + int ctrl; + + /* IRQ */ + DPRINTF(("IRQ\n")); + ykbec_apmspl = splhigh(); + /* enable isa irq 1 and 12 (PS/2 input devices) */ + loongson_set_isa_imr(0xffff & ~(1 << 1) & ~(1 << 12)); + + /* USB */ + DPRINTF(("USB\n")); + ykbec_write(sc, REG_USB0, USB_FLAG_OFF); + ykbec_write(sc, REG_USB1, USB_FLAG_OFF); + ykbec_write(sc, REG_USB2, USB_FLAG_OFF); + + /* EC */ + DPRINTF(("REG_PMUCFG\n")); + ctrl = PMUCFG_SCI_WAKEUP | PMUCFG_WDT_WAKEUP | PMUCFG_GPWU_WAKEUP | + PMUCFG_LPC_WAKEUP | PMUCFG_STOP_MODE | PMUCFG_RESET_8051; + ykbec_write(sc, REG_PMUCFG, ctrl); + + /* FAN */ + DPRINTF(("FAN\n")); + ykbec_write(sc, REG_FAN_CONTROL, REG_FAN_OFF); + + /* CPU */ + DPRINTF(("CPU\n")); + ykbec_chip_config = REGVAL(LOONGSON_CHIP_CONFIG0); + REGVAL(LOONGSON_CHIP_CONFIG0) = ykbec_chip_config & ~0x7; + (void)REGVAL(LOONGSON_CHIP_CONFIG0); + + return 0; +} + +int +ykbec_resume() +{ + struct ykbec_softc *sc = ykbec_sc; + + /* IRQ */ + DPRINTF(("IRQ\n")); + splx(ykbec_apmspl); + + /* CPU */ + DPRINTF(("CPU\n")); + REGVAL(LOONGSON_CHIP_CONFIG0) = ykbec_chip_config; + (void)REGVAL(LOONGSON_CHIP_CONFIG0); + + /* FAN */ + DPRINTF(("FAN\n")); + ykbec_write(sc, REG_FAN_CONTROL, REG_FAN_ON); + + /* USB */ + DPRINTF(("USB\n")); + ykbec_write(sc, REG_USB0, USB_FLAG_ON); + ykbec_write(sc, REG_USB1, USB_FLAG_ON); + ykbec_write(sc, REG_USB2, USB_FLAG_ON); + + return 0; +} #endif #if NPCKBD > 0 || NHIDKBD > 0 |