Module Name: src Committed By: phx Date: Sat Jan 14 19:39:25 UTC 2012
Modified Files: src/sys/arch/sandpoint/conf: GENERIC KUROBOX files.sandpoint src/sys/arch/sandpoint/include: bus_funcs.h src/sys/arch/sandpoint/sandpoint: machdep.c mainbus.c Added Files: src/sys/arch/sandpoint/sandpoint: nhpow.c Log Message: New device nhpow(4) to support the onboard GPIO pins on a NH230/231 board for buttons, powerdown, reset, LEDs and fan control. It attaches gpio(4) for its 8 pins on demand. To generate a diff of this commit: cvs rdiff -u -r1.65 -r1.66 src/sys/arch/sandpoint/conf/GENERIC cvs rdiff -u -r1.3 -r1.4 src/sys/arch/sandpoint/conf/KUROBOX cvs rdiff -u -r1.30 -r1.31 src/sys/arch/sandpoint/conf/files.sandpoint cvs rdiff -u -r1.2 -r1.3 src/sys/arch/sandpoint/include/bus_funcs.h cvs rdiff -u -r1.60 -r1.61 src/sys/arch/sandpoint/sandpoint/machdep.c cvs rdiff -u -r1.26 -r1.27 src/sys/arch/sandpoint/sandpoint/mainbus.c cvs rdiff -u -r0 -r1.1 src/sys/arch/sandpoint/sandpoint/nhpow.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/sandpoint/conf/GENERIC diff -u src/sys/arch/sandpoint/conf/GENERIC:1.65 src/sys/arch/sandpoint/conf/GENERIC:1.66 --- src/sys/arch/sandpoint/conf/GENERIC:1.65 Sat Jan 7 20:51:23 2012 +++ src/sys/arch/sandpoint/conf/GENERIC Sat Jan 14 19:39:25 2012 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.65 2012/01/07 20:51:23 phx Exp $ +# $NetBSD: GENERIC,v 1.66 2012/01/14 19:39:25 phx Exp $ # # machine description file for GENERIC NAS # @@ -22,7 +22,7 @@ include "arch/sandpoint/conf/std.sandpo options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "GENERIC-$Revision: 1.65 $" +#ident "GENERIC-$Revision: 1.66 $" maxusers 32 @@ -179,6 +179,8 @@ cpu* at mainbus0 #nor* at cfi? #flash* at nor? +nhpow0 at mainbus0 # NH230/231 power,LED,buttons + pci* at mainbus0 bus ? pchb* at pci? dev ? function ? # PCI host bridge @@ -225,6 +227,9 @@ rgephy* at mii? phy ? # Realtek 8169S/ makphy* at mii? phy ? # Marvell Semiconductor 88E1000 PHYs ukphy* at mii? phy ? # generic unknown PHYs +# GPIO devices +gpio* at gpiobus? + # USB Controller and Devices ehci* at pci? dev ? function ? # Enhanced Host Controller ohci* at pci? dev ? function ? # Open Host Controller Index: src/sys/arch/sandpoint/conf/KUROBOX diff -u src/sys/arch/sandpoint/conf/KUROBOX:1.3 src/sys/arch/sandpoint/conf/KUROBOX:1.4 --- src/sys/arch/sandpoint/conf/KUROBOX:1.3 Wed Jun 9 17:34:32 2010 +++ src/sys/arch/sandpoint/conf/KUROBOX Sat Jan 14 19:39:25 2012 @@ -1,4 +1,4 @@ -# $NetBSD: KUROBOX,v 1.3 2010/06/09 17:34:32 phx Exp $ +# $NetBSD: KUROBOX,v 1.4 2012/01/14 19:39:25 phx Exp $ # # KuroBox/LinkStation support # @@ -10,3 +10,6 @@ no satmgr0 com0 at eumb? unit 1 # console at 0x4600 #com1 at eumb? unit 0 satmgr0 at eumb? unit 0 # satmgr at 0x4500 + +no nhpow0 +no gpio* Index: src/sys/arch/sandpoint/conf/files.sandpoint diff -u src/sys/arch/sandpoint/conf/files.sandpoint:1.30 src/sys/arch/sandpoint/conf/files.sandpoint:1.31 --- src/sys/arch/sandpoint/conf/files.sandpoint:1.30 Sat Dec 17 20:20:37 2011 +++ src/sys/arch/sandpoint/conf/files.sandpoint Sat Jan 14 19:39:25 2012 @@ -1,4 +1,4 @@ -# $NetBSD: files.sandpoint,v 1.30 2011/12/17 20:20:37 phx Exp $ +# $NetBSD: files.sandpoint,v 1.31 2012/01/14 19:39:25 phx Exp $ # # Motorola's "SandPoint" evaluation board and multiplied descendents. # @@ -31,12 +31,12 @@ include "dev/ata/files.ata" # # Memory Disk for install floppy # -file dev/md_root.c memory_disk_hooks +file dev/md_root.c memory_disk_hooks # # System bus types # -define mainbus { } +define mainbus { } device mainbus: isabus, pcibus, mainbus attach mainbus at root @@ -48,15 +48,19 @@ device cfi: norbus attach cfi at mainbus with sandpointcfi file arch/sandpoint/sandpoint/flash_cfi.c sandpointcfi -device eumb { [ unit = -1 ] }: mainbus -attach eumb at mainbus +device nhpow: sysmon_power, sysmon_taskq, gpiobus +attach nhpow at mainbus +file arch/sandpoint/sandpoint/nhpow.c nhpow + +device eumb { [ unit = -1 ] }: mainbus +attach eumb at mainbus file arch/sandpoint/sandpoint/eumb.c eumb -attach com at eumb with com_eumb +attach com at eumb with com_eumb file arch/sandpoint/sandpoint/com_eumb.c com_eumb needs-flag device ociic: motoi2c, i2cbus -attach ociic at eumb with iic_eumb +attach ociic at eumb with iic_eumb file arch/sandpoint/sandpoint/iic_eumb.c iic_eumb device satmgr: sysmon_power, sysmon_taskq Index: src/sys/arch/sandpoint/include/bus_funcs.h diff -u src/sys/arch/sandpoint/include/bus_funcs.h:1.2 src/sys/arch/sandpoint/include/bus_funcs.h:1.3 --- src/sys/arch/sandpoint/include/bus_funcs.h:1.2 Sat Dec 17 20:20:37 2011 +++ src/sys/arch/sandpoint/include/bus_funcs.h Sat Jan 14 19:39:25 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: bus_funcs.h,v 1.2 2011/12/17 20:20:37 phx Exp $ */ +/* $NetBSD: bus_funcs.h,v 1.3 2012/01/14 19:39:25 phx Exp $ */ /* $OpenBSD: bus.h,v 1.1 1997/10/13 10:53:42 pefo Exp $ */ #ifndef _SANDPOINT_BUS_FUNCS_H_ @@ -11,6 +11,7 @@ extern struct powerpc_bus_space sandpoin extern struct powerpc_bus_space genppc_isa_mem_space_tag; extern struct powerpc_bus_space sandpoint_eumb_space_tag; extern struct powerpc_bus_space sandpoint_flash_space_tag; +extern struct powerpc_bus_space sandpoint_nhgpio_space_tag; #endif #include <powerpc/bus_funcs.h> Index: src/sys/arch/sandpoint/sandpoint/machdep.c diff -u src/sys/arch/sandpoint/sandpoint/machdep.c:1.60 src/sys/arch/sandpoint/sandpoint/machdep.c:1.61 --- src/sys/arch/sandpoint/sandpoint/machdep.c:1.60 Sat Dec 17 20:20:38 2011 +++ src/sys/arch/sandpoint/sandpoint/machdep.c Sat Jan 14 19:39:25 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.60 2011/12/17 20:20:38 phx Exp $ */ +/* $NetBSD: machdep.c,v 1.61 2012/01/14 19:39:25 phx Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.60 2011/12/17 20:20:38 phx Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.61 2012/01/14 19:39:25 phx Exp $"); #include "opt_compat_netbsd.h" #include "opt_ddb.h" @@ -122,12 +122,12 @@ extern struct consdev kcomcons; void initppc(u_int startkernel, u_int endkernel, u_int args, void *btinfo) { + extern u_long ticks_per_sec, ns_per_tick; struct btinfo_magic *bi_magic = btinfo; struct btinfo_memory *meminfo; struct btinfo_clock *clockinfo; size_t memsize; u_long ticks; - extern u_long ticks_per_sec, ns_per_tick; if ((unsigned)btinfo != 0 && (unsigned)btinfo < startkernel && bi_magic->magic == BOOTINFO_MAGIC) @@ -173,6 +173,7 @@ initppc(u_int startkernel, u_int endkern oea_batinit( 0x80000000, BAT_BL_256M, /* SANDPOINT_BUS_SPACE_MEM */ 0xfc000000, BAT_BL_64M, /* _EUMB|_IO */ + 0x70000000, BAT_BL_128K, /* only for NH230 board control */ 0); /* Install vectors and interrupt handler */ @@ -452,8 +453,12 @@ struct powerpc_bus_space sandpoint_flash _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 0x00000000, 0xff000000, 0x00000000, }; +struct powerpc_bus_space sandpoint_nhgpio_space_tag = { + _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE, + 0x70000000, 0x00000000, 0x00001000, +}; -static char ex_storage[6][EXTENT_FIXED_STORAGE_SIZE(8)] +static char ex_storage[7][EXTENT_FIXED_STORAGE_SIZE(8)] __attribute__((aligned(8))); void @@ -496,6 +501,12 @@ sandpoint_bus_space_init(void) ex_storage[5], sizeof(ex_storage[5])); if (error) panic("sandpoint_bus_space_init: can't init flash tag"); + + /* NH230/231 only: extended ROM space at 0x70000000 for GPIO */ + error = bus_space_init(&sandpoint_nhgpio_space_tag, "nh23x-gpio", + ex_storage[6], sizeof(ex_storage[6])); + if (error) + panic("sandpoint_bus_space_init: can't init nhgpio tag"); } #define MPC107_EUMBBAR 0x78 /* Eumb base address */ Index: src/sys/arch/sandpoint/sandpoint/mainbus.c diff -u src/sys/arch/sandpoint/sandpoint/mainbus.c:1.26 src/sys/arch/sandpoint/sandpoint/mainbus.c:1.27 --- src/sys/arch/sandpoint/sandpoint/mainbus.c:1.26 Sun Dec 18 14:28:59 2011 +++ src/sys/arch/sandpoint/sandpoint/mainbus.c Sat Jan 14 19:39:25 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: mainbus.c,v 1.26 2011/12/18 14:28:59 phx Exp $ */ +/* $NetBSD: mainbus.c,v 1.27 2012/01/14 19:39:25 phx Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.26 2011/12/18 14:28:59 phx Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.27 2012/01/14 19:39:25 phx Exp $"); #include "opt_pci.h" #include "pci.h" @@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: mainbus.c,v #include <sys/systm.h> #include <machine/autoconf.h> +#include <machine/bootinfo.h> #include <machine/isa_machdep.h> #include <dev/pci/pcivar.h> @@ -75,6 +76,7 @@ mainbus_attach(device_t parent, device_t { struct mainbus_attach_args mba; struct pcibus_attach_args pba; + struct btinfo_prodfamily *pfam; #if defined(PCI_NETBSD_CONFIGURE) struct extent *ioext, *memext; #endif @@ -89,6 +91,14 @@ mainbus_attach(device_t parent, device_t mba.ma_bst = &sandpoint_eumb_space_tag; config_found_ia(self, "mainbus", &mba, mainbus_print); + pfam = lookup_bootinfo(BTINFO_PRODFAMILY); + if (pfam != NULL && strcmp(pfam->name, "nhnas") == 0) { + /* attach nhpow(4) for NH230/231 only */ + mba.ma_name = "nhpow"; + mba.ma_bst = &sandpoint_nhgpio_space_tag; + config_found_ia(self, "mainbus", &mba, mainbus_print); + } + mba.ma_name = "cfi"; mba.ma_bst = &sandpoint_flash_space_tag; mba.ma_addr = 0xffe00000; /* smallest flash is 2 MiB */ Added files: Index: src/sys/arch/sandpoint/sandpoint/nhpow.c diff -u /dev/null src/sys/arch/sandpoint/sandpoint/nhpow.c:1.1 --- /dev/null Sat Jan 14 19:39:25 2012 +++ src/sys/arch/sandpoint/sandpoint/nhpow.c Sat Jan 14 19:39:25 2012 @@ -0,0 +1,324 @@ +/* $NetBSD: nhpow.c,v 1.1 2012/01/14 19:39:25 phx Exp $ */ + +/*- + * Copyright (c) 2012 Frank Wille. + * All rights reserved. + * + * Written by Frank Wille for The NetBSD Project. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NH230/231 power and LED control, button handling + */ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: nhpow.c,v 1.1 2012/01/14 19:39:25 phx Exp $"); +#include "gpio.h" + +#include <sys/param.h> +#include <sys/device.h> +#if NGPIO > 0 +#include <sys/gpio.h> +#endif +#include <sys/callout.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/reboot.h> +#include <sys/sysctl.h> + +#if NGPIO > 0 +#include <dev/gpio/gpiovar.h> +#endif +#include <dev/sysmon/sysmonvar.h> +#include <dev/sysmon/sysmon_taskq.h> + +#include <machine/autoconf.h> + +static int nhpow_match(device_t, cfdata_t, void *); +static void nhpow_attach(device_t, device_t, void *); +static void nhpow_reboot(int); +static int nhpow_sysctl_fan(SYSCTLFN_PROTO); +static int hwintr(void *); +static void guarded_pbutton(void *); +static void sched_sysmon_pbutton(void *); + +static void nhgpio_pin_write(void *, int, int); +#if NGPIO > 0 +static int nhgpio_pin_read(void *, int); +static void nhgpio_pin_ctl(void *, int, int); +#endif + +#define NHGPIO_PINS 8 + +/* write gpio */ +#define NHGPIO_WRITE(sc,x) bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0, x) +#define NHGPIO_POWEROFF 0x01 +#define NHGPIO_RESET 0x02 +#define NHGPIO_STATUS_LED_OFF 0x04 +#define NHGPIO_FAN_HIGH 0x08 +#define NHGPIO_USB1_LED_OFF 0x40 +#define NHGPIO_USB2_LED_OFF 0x80 + +/* read gpio */ +#define NHGPIO_READ(sc) bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0) +#define NHGPIO_POWERBUTTON 0x01 +#define NHGPIO_RESETBUTTON 0x02 +#define NHGPIO_VERSIONMASK 0xf0 +#define NHGPIO_VERSIONSHIFT 4 + +struct nhpow_softc { + device_t sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + callout_t sc_ch_pbutton; + struct sysmon_pswitch sc_sm_pbutton; + int sc_sysctl_fan; +#if NGPIO > 0 + struct gpio_chipset_tag sc_gpio_gc; + gpio_pin_t sc_gpio_pins[8]; +#endif + uint8_t sc_gpio_wrstate; +}; + +CFATTACH_DECL_NEW(nhpow, sizeof(struct nhpow_softc), + nhpow_match, nhpow_attach, NULL, NULL); + +static int found = 0; + +extern struct cfdriver nhpow_cd; +extern void (*md_reboot)(int); + +static int +nhpow_match(device_t parent, cfdata_t cf, void *aux) +{ + struct mainbus_attach_args *ma = aux; + + if (found != 0 || strcmp(ma->ma_name, nhpow_cd.cd_name) != 0) + return 0; + + return 1; +} + +static void +nhpow_attach(device_t parent, device_t self, void *aux) +{ + struct mainbus_attach_args *ma = aux; +#if NGPIO > 0 + struct gpiobus_attach_args gba; +#endif + const struct sysctlnode *rnode; + struct sysctllog *clog; + struct nhpow_softc *sc; + int i; + + found = 1; + sc = device_private(self); + sc->sc_dev = self; + + /* map the first byte for GPIO */ + KASSERT(ma->ma_bst != NULL); + sc->sc_iot = ma->ma_bst; + i = bus_space_map(sc->sc_iot, 0, 1, 0, &sc->sc_ioh); + if (i != 0) { + aprint_error(": could not map error %d\n", i); + return; + } + + aprint_naive(": Power Button Manager\n"); + aprint_normal(": NH230/231 gpio board control, version %u\n", + (NHGPIO_READ(sc) & NHGPIO_VERSIONMASK) >> NHGPIO_VERSIONSHIFT); + + md_reboot = nhpow_reboot; /* cpu_reboot() hook */ + callout_init(&sc->sc_ch_pbutton, 0); /* power-button callout */ + + /* establish button interrupt handler */ + intr_establish(I8259_ICU + 4, IST_EDGE_RISING, IPL_SCHED, hwintr, sc); + aprint_normal_dev(self, "interrupting at irq %d\n", I8259_ICU + 4); + + /* register power button with sysmon */ + sysmon_task_queue_init(); + memset(&sc->sc_sm_pbutton, 0, sizeof(struct sysmon_pswitch)); + sc->sc_sm_pbutton.smpsw_name = device_xname(sc->sc_dev); + sc->sc_sm_pbutton.smpsw_type = PSWITCH_TYPE_POWER; + if (sysmon_pswitch_register(&sc->sc_sm_pbutton) != 0) + aprint_error_dev(sc->sc_dev, + "unable to register power button with sysmon\n"); + + /* create machdep.nhpow subtree for fan control */ + clog = NULL; + sysctl_createv(&clog, 0, NULL, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "machdep", NULL, + NULL, 0, NULL, 0, + CTL_MACHDEP, CTL_EOL); + sysctl_createv(&clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "nhpow", NULL, + NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + sysctl_createv(&clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "fan", + SYSCTL_DESCR("Toggle high(1)/low(0) fan speed"), + nhpow_sysctl_fan, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + + /* define initial output state */ + sc->sc_sysctl_fan = 0; + sc->sc_gpio_wrstate = NHGPIO_USB1_LED_OFF | NHGPIO_USB2_LED_OFF; + NHGPIO_WRITE(sc, sc->sc_gpio_wrstate); + +#if NGPIO > 0 + /* initialize gpio pin array */ + for (i = 0; i < NHGPIO_PINS; i++) { + sc->sc_gpio_pins[i].pin_num = i; + sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INOUT; + sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_INOUT; + sc->sc_gpio_pins[i].pin_state = + (sc->sc_gpio_wrstate & (1 << i)) ? + GPIO_PIN_HIGH : GPIO_PIN_LOW; + } + + /* create controller tag and attach GPIO framework */ + sc->sc_gpio_gc.gp_cookie = sc; + sc->sc_gpio_gc.gp_pin_read = nhgpio_pin_read; + sc->sc_gpio_gc.gp_pin_write = nhgpio_pin_write; + sc->sc_gpio_gc.gp_pin_ctl = nhgpio_pin_ctl; + gba.gba_gc = &sc->sc_gpio_gc; + gba.gba_pins = sc->sc_gpio_pins; + gba.gba_npins = NHGPIO_PINS; + config_found(self, &gba, gpiobus_print); +#endif +} + +static void +nhgpio_pin_write(void *arg, int pin, int value) +{ + struct nhpow_softc *sc = arg; + int p; + + KASSERT(sc != NULL); + p = pin % NHGPIO_PINS; + if (value) + sc->sc_gpio_wrstate |= (1 << p); + else + sc->sc_gpio_wrstate &= ~(1 << p); + NHGPIO_WRITE(sc, sc->sc_gpio_wrstate); +} + +#if NGPIO > 0 +static int +nhgpio_pin_read(void *arg, int pin) +{ + struct nhpow_softc *sc = arg; + int p; + + KASSERT(sc != NULL); + p = pin % NHGPIO_PINS; + return (NHGPIO_READ(sc) >> p) & 1; +} + +static void +nhgpio_pin_ctl(void *arg, int pin, int flags) +{ + + /* nothing to control */ +} +#endif + +static void +nhpow_reboot(int howto) +{ + struct nhpow_softc *sc = device_lookup_private(&nhpow_cd, 0); + + if ((howto & RB_POWERDOWN) == RB_AUTOBOOT) + NHGPIO_WRITE(sc, NHGPIO_STATUS_LED_OFF | NHGPIO_RESET); + else + NHGPIO_WRITE(sc, NHGPIO_STATUS_LED_OFF | NHGPIO_POWEROFF); + + tsleep(nhpow_reboot, PWAIT, "reboot", 0); + /*NOTREACHED*/ +} + +static int +nhpow_sysctl_fan(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + struct nhpow_softc *sc; + int error, t; + + sc = device_lookup_private(&nhpow_cd, 0); + node = *rnode; + t = sc->sc_sysctl_fan; + node.sysctl_data = &t; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + if (t < 0 || t > 1) + return EINVAL; + + if (sc->sc_sysctl_fan != t) { + sc->sc_sysctl_fan = t; + nhgpio_pin_write(sc, 3, t); /* set new fan speed */ + } + return 0; +} + +static int +hwintr(void *arg) +{ + struct nhpow_softc *sc = arg; + uint8_t buttons; + + callout_stop(&sc->sc_ch_pbutton); + + buttons = NHGPIO_READ(sc); + if (!(buttons & NHGPIO_POWERBUTTON)) { + /* power button, schedule 3 seconds poweroff guard time */ + callout_reset(&sc->sc_ch_pbutton, 3 * hz, guarded_pbutton, sc); + } + if (!(buttons & NHGPIO_RESETBUTTON)) { + /* reset/setup button */ + } + + return 1; +} + +static void +guarded_pbutton(void *arg) +{ + struct nhpow_softc *sc = arg; + + /* we're now in callout(9) context */ + if (!(NHGPIO_READ(sc) & NHGPIO_POWERBUTTON)) + sysmon_task_queue_sched(0, sched_sysmon_pbutton, sc); +} + +static void +sched_sysmon_pbutton(void *arg) +{ + struct nhpow_softc *sc = arg; + + /* we're now in kthread(9) context */ + sysmon_pswitch_event(&sc->sc_sm_pbutton, PSWITCH_EVENT_PRESSED); +}