Module Name:    src
Committed By:   hkenken
Date:           Sat Mar 29 12:00:27 UTC 2014

Modified Files:
        src/sys/arch/arm/imx: imxspi.c
        src/sys/arch/evbarm/conf: NETWALKER files.netwalker
        src/sys/arch/evbarm/netwalker: netwalker_machdep.c
Added Files:
        src/sys/arch/evbarm/netwalker: netwalker_btn.c netwalker_spi.c
        src/sys/dev/spi: oj6sh.c

Log Message:
Add optical joystick support for NetWalker.
+ OJ6SH-T25 (Sharp "Optical TOUCH CRUISER" sensor)
+ 2 Mouse buttons (GPIO)


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/imx/imxspi.c
cvs rdiff -u -r1.24 -r1.25 src/sys/arch/evbarm/conf/NETWALKER
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/evbarm/conf/files.netwalker
cvs rdiff -u -r0 -r1.1 src/sys/arch/evbarm/netwalker/netwalker_btn.c \
    src/sys/arch/evbarm/netwalker/netwalker_spi.c
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/evbarm/netwalker/netwalker_machdep.c
cvs rdiff -u -r0 -r1.1 src/sys/dev/spi/oj6sh.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/arm/imx/imxspi.c
diff -u src/sys/arch/arm/imx/imxspi.c:1.1 src/sys/arch/arm/imx/imxspi.c:1.2
--- src/sys/arch/arm/imx/imxspi.c:1.1	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imxspi.c	Sat Mar 29 12:00:27 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: imxspi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+/*	$NetBSD: imxspi.c,v 1.2 2014/03/29 12:00:27 hkenken Exp $	*/
 
 /*-
  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1.2 2014/03/29 12:00:27 hkenken Exp $");
 
 #include "opt_imx.h"
 #include "opt_imxspi.h"
@@ -391,7 +391,7 @@ imxspi_intr(void *arg)
 	/* RXFIFO ready */
 	if (sr & IMXSPI(INTR_RR_EN)) {
 		imxspi_recv(sc);
-		if(sc->sc_wchunk == NULL &&sc->sc_rchunk == NULL)
+		if (sc->sc_wchunk == NULL && sc->sc_rchunk == NULL)
 			imxspi_done(sc, err);
 	}
 
@@ -408,7 +408,7 @@ imxspi_transfer(void *arg, struct spi_tr
 	int s;
 
 	/* make sure we select the right chip */
-	s = splserial();
+	s = splbio();
 	spi_transq_enqueue(&sc->sc_q, st);
 	if (sc->sc_running == FALSE)
 		imxspi_sched(sc);

Index: src/sys/arch/evbarm/conf/NETWALKER
diff -u src/sys/arch/evbarm/conf/NETWALKER:1.24 src/sys/arch/evbarm/conf/NETWALKER:1.25
--- src/sys/arch/evbarm/conf/NETWALKER:1.24	Mon Mar 24 14:15:37 2014
+++ src/sys/arch/evbarm/conf/NETWALKER	Sat Mar 29 12:00:27 2014
@@ -1,4 +1,4 @@
-#	$NetBSD: NETWALKER,v 1.24 2014/03/24 14:15:37 szptvlfn Exp $
+#	$NetBSD: NETWALKER,v 1.25 2014/03/29 12:00:27 hkenken Exp $
 #
 #	NETWALKER -- http://www.sharp.co.jp/netwalker/
 #
@@ -128,7 +128,7 @@ options 	NO_POWERSAVE	# uncomment this t
 
 # Development and Debugging options
 #options 	PERFCTRS	# performance counters
-options 	DIAGNOSTIC	# internally consistency checks
+#options 	DIAGNOSTIC	# internally consistency checks
 #options 	DEBUG
 #options 	KMEMSTATS	# kernel memory statistics (vmstat -m)
 options 	DDB		# in-kernel debugger
@@ -151,6 +151,7 @@ makeoptions	DEBUG="-g"	# compile full sy
 
 # Kernel root file system and dump configuration.
 config		netbsd		root on ? type ?
+config		netbsd-ld0	root on ld0 type ffs
 
 # The main bus device
 mainbus0	at root
@@ -175,6 +176,7 @@ imxuart0	at axi? addr 0x73fbc000 irq 31	
 # Clock Control
 imxccm0		at axi? addr 0x73fd4000
 options		IMX51_CKIL_FREQ=32768
+#options	IMXCCMDEBUG
 
 # Enhanced Periodic Interrupt Timer
 imxclock0	at axi? addr 0x73fac000 size 0x4000 irq 40
@@ -183,11 +185,46 @@ imxclock1	at axi? addr 0x73fb0000 size 0
 # IOMUX
 imxiomux0	at axi? addr 0x73fa8000
 
+# WatchDog
+imxwdog0	at axi? addr 0x73f98000 irq 58 flags 0
+
 # GPIO
-imxgpio0	at axi? addr 0x73f84000
-imxgpio1	at axi? addr 0x73f88000
-imxgpio2	at axi? addr 0x73f8c000
-imxgpio3	at axi? addr 0x73f90000
+imxgpio0	at axi? addr 0x73f84000 irqbase 128 irq 50
+imxgpio1	at axi? addr 0x73f88000 irqbase 160 irq 52
+imxgpio2	at axi? addr 0x73f8c000 irqbase 192 irq 54
+imxgpio3	at axi? addr 0x73f90000 irqbase 224 irq 56
+gpio*		at imxgpio?
+options		IMX_GPIO_INTR_SPLIT
+
+# I2C
+#imxi2c0	at axi? addr 0x83fc8000 irq 62
+#imxi2c1	at axi? addr 0x83fc4000 irq 63
+
+# IIC
+#iic*	   at imxi2c?
+
+# SPI bus
+imxspi0		at axi? addr 0x70010000 irq 36 flags 1
+#imxspi1	at axi? addr 0x83fac000 irq 37 flags 1
+#imxspi2	at axi? addr 0x83fc0000 irq 38 flags 0
+spi0		at imxspi0 # eCSPI1
+#spi1		at imxspi1 # eCSPI2
+#spi2		at imxspi2 # CSPI1
+options		IMXSPINSLAVES=3
+#options	IMXSPI_DEBUG=10
+
+# Optical Joystick
+mousebtn0	at gpio1 offset 22 mask 0x03 # intr 182, 183
+#options	MOUSEBTN_POLLING
+oj6sh0		at spi0 slave 2
+#options	OJ6SH_DEBUG=4
+options		OJ6SH_UP_X_LEFT_Y
+wsmouse*	at oj6sh? mux 0
+wsmouse*	at mousebtn? mux 0
+
+# SPI NOR-Flash
+#spiflash0	at spiflashbus?
+#m25p0		at spi0 slave 1
 
 # SD/MMC
 sdhc0    	at axi? addr 0x70004000 irq 1	     # eSDHC1
@@ -238,9 +275,9 @@ pseudo-device	swcrypto		# software crypt
 
 # disk/mass storage pseudo-devices
 #pseudo-device	md			# memory disk device (ramdisk)
-#pseudo-device	vnd			# disk-like interface to files
+pseudo-device	vnd			# disk-like interface to files
 #pseudo-device	fss			# file system snapshot device
-#pseudo-device	putter			# for puffs and pud
+pseudo-device	putter			# for puffs and pud
 
 # network pseudo-devices
 pseudo-device	bpfilter		# Berkeley packet filter
@@ -250,12 +287,20 @@ pseudo-device	loop			# network loopback
 
 # miscellaneous pseudo-devices
 pseudo-device	pty			# pseudo-terminals
-pseudo-device	ksyms			# /dev/ksyms
 pseudo-device	clockctl		# NTP clockctl
+pseudo-device	ksyms			# /dev/ksyms
+pseudo-device	lockstat		# lock profiling
 
 # wscons pseudo-devices
 pseudo-device	wsmux			# mouse & keyboard multiplexor
 pseudo-device	wsfont
 
+# data mover pseudo-devices
+#pseudo-device	swdmover		# software dmover(9) back-end
+#pseudo-device	dmoverio		# /dev/dmover dmover(9) interface
+
+# userland interface to drivers, including autoconf and properties retrieval
+pseudo-device 	drvctl
+
 # local configuration
 cinclude "arch/evbarm/conf/NETWALKER.local"

Index: src/sys/arch/evbarm/conf/files.netwalker
diff -u src/sys/arch/evbarm/conf/files.netwalker:1.4 src/sys/arch/evbarm/conf/files.netwalker:1.5
--- src/sys/arch/evbarm/conf/files.netwalker:1.4	Fri Jan 24 02:06:03 2014
+++ src/sys/arch/evbarm/conf/files.netwalker	Sat Mar 29 12:00:27 2014
@@ -1,6 +1,6 @@
-#	$NetBSD: files.netwalker,v 1.4 2014/01/24 02:06:03 hkenken Exp $
+#	$NetBSD: files.netwalker,v 1.5 2014/03/29 12:00:27 hkenken Exp $
 #
-# Sharp Netwalker
+# Sharp Netwalker configuration info
 #
 
 file   arch/arm/arm32/arm32_boot.c
@@ -23,3 +23,23 @@ file   arch/evbarm/netwalker/netwalker_u
 attach	ipu at axi with lcd_netwalker
 file	arch/evbarm/netwalker/netwalker_lcd.c	lcd_netwalker
 defflag	opt_netwalker_lcd.h			LCD_DEBUG
+
+# CSPI & eCSPI Controller
+attach	imxspi at axi with spi_netwalker
+file	arch/evbarm/netwalker/netwalker_spi.c	spi_netwalker
+
+# Mouse button
+device	mousebtn: wsmousedev
+attach	mousebtn at gpio with btn_netwalker
+file	arch/evbarm/netwalker/netwalker_btn.c	btn_netwalker
+defflag	opt_mousebtn.h				MOUSEBTN_POLLING
+
+# OJ6SH-T25 Optical Joystick
+device  oj6sh: wsmousedev
+attach  oj6sh at spi
+file    dev/spi/oj6sh.c				oj6sh
+defflag	opt_oj6sh.h				OJ6SH_UP_Y_RIGHT_X
+						OJ6SH_DOWN_Y_LEFT_X
+						OJ6SH_UP_X_LEFT_Y
+						OJ6SH_DOWN_X_RIGHT_Y
+

Index: src/sys/arch/evbarm/netwalker/netwalker_machdep.c
diff -u src/sys/arch/evbarm/netwalker/netwalker_machdep.c:1.13 src/sys/arch/evbarm/netwalker/netwalker_machdep.c:1.14
--- src/sys/arch/evbarm/netwalker/netwalker_machdep.c:1.13	Fri Jan 24 02:06:03 2014
+++ src/sys/arch/evbarm/netwalker/netwalker_machdep.c	Sat Mar 29 12:00:27 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: netwalker_machdep.c,v 1.13 2014/01/24 02:06:03 hkenken Exp $	*/
+/*	$NetBSD: netwalker_machdep.c,v 1.14 2014/03/29 12:00:27 hkenken Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003, 2005, 2010  Genetec Corporation.
@@ -102,8 +102,10 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netwalker_machdep.c,v 1.13 2014/01/24 02:06:03 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netwalker_machdep.c,v 1.14 2014/03/29 12:00:27 hkenken Exp $");
 
+#include "opt_evbarm_boardtype.h"
+#include "opt_cputypes.h"
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
 #include "opt_md.h"
@@ -467,6 +469,8 @@ const struct iomux_setup iomux_setup_dat
 	IOMUX_MP(EIM_D27, ALT3, KEEPER | PU_100K | DSEHIGH | SRE), /* RTS */
 	IOMUX_M(NANDF_D15, ALT3),	/* GPIO3_25 */
 	IOMUX_MP(NANDF_D14, ALT3, HYS | PULL | PU_100K ),	/* GPIO3_26 */
+
+	/* OJ6SH-T25 */
 	IOMUX_M(CSI1_D9, ALT3),			/* GPIO3_13 */
 	IOMUX_M(CSI1_VSYNC, ALT3),		/* GPIO3_14 */
 	IOMUX_M(CSI1_HSYNC, ALT3),		/* GPIO3_15 */
@@ -488,13 +492,15 @@ const struct iomux_setup iomux_setup_dat
 	/* XXX more audio pins ? */
 
 	/* CSPI */
-	/* ??? doesn't work ??? */
-	IOMUX_P(CSPI1_MOSI, HYS | PULL | PD_100K | DSEHIGH | SRE),
-	IOMUX_P(CSPI1_MISO, HYS | PULL | PD_100K | DSEHIGH | SRE),
-	IOMUX_M(CSPI1_SS0, ALT3),
-	IOMUX_MP(CSPI1_SS1, ALT0, HYS | KEEPER | DSEHIGH | SRE),
-	IOMUX_MP(DI1_PIN11, ALT7, HYS | PULL | DSEHIGH | SRE),
-	IOMUX_P(CSPI1_SCLK, HYS | KEEPER | DSEHIGH | SRE),
+	IOMUX_MP(CSPI1_MOSI, ALT0, HYS | PULL | PD_100K | DSEHIGH | SRE),
+	IOMUX_MP(CSPI1_MISO, ALT0, HYS | PULL | PD_100K | DSEHIGH | SRE),
+	IOMUX_MP(CSPI1_SCLK, ALT0, HYS | PULL | PD_100K | DSEHIGH | SRE),
+
+	/* SPI CS */
+	IOMUX_MP(CSPI1_SS0, ALT3, HYS | KEEPER | DSEHIGH | SRE), /* GPIO4[24] */
+	IOMUX_MP(CSPI1_SS1, ALT3, HYS | KEEPER | DSEHIGH | SRE), /* GPIO4[25] */
+	IOMUX_MP(DI1_PIN11, ALT4, HYS | PULL | DSEHIGH | SRE),   /* GPIO3[0] */
+
 	/* 26M Osc */
 	IOMUX_MP(DI1_PIN12, ALT4, KEEPER | DSEHIGH | SRE), /* GPIO3_1 */
 
@@ -504,7 +510,7 @@ const struct iomux_setup iomux_setup_dat
 	IOMUX_MP(KEY_COL5, SION | ALT3, HYS | ODE | DSEHIGH | SRE),
 	IOMUX_DATA(IOMUXC_I2C2_IPP_SDA_IN_SELECT_INPUT, INPUT_DAISY_1),
 	IOMUX_DATA(IOMUXC_UART3_IPP_UART_RTS_B_SELECT_INPUT, INPUT_DAISY_3),
-#if 1
+
 	/* NAND */
 	IOMUX_MP(NANDF_WE_B, ALT0, HVE | DSEHIGH | PULL | PU_47K),
 	IOMUX_MP(NANDF_RE_B, ALT0, HVE | DSEHIGH | PULL | PU_47K),
@@ -521,7 +527,6 @@ const struct iomux_setup iomux_setup_dat
 	IOMUX_MP(NANDF_D2, ALT0, HVE | DSEHIGH | KEEPER | PU_100K),
 	IOMUX_MP(NANDF_D1, ALT0, HVE | DSEHIGH | KEEPER | PU_100K),
 	IOMUX_MP(NANDF_D0, ALT0, HVE | DSEHIGH | KEEPER | PU_100K),
-#endif
 
 	/* Batttery pins */
 	IOMUX_MP(NANDF_D13, ALT3, HYS | DSEHIGH),

Added files:

Index: src/sys/arch/evbarm/netwalker/netwalker_btn.c
diff -u /dev/null src/sys/arch/evbarm/netwalker/netwalker_btn.c:1.1
--- /dev/null	Sat Mar 29 12:00:27 2014
+++ src/sys/arch/evbarm/netwalker/netwalker_btn.c	Sat Mar 29 12:00:27 2014
@@ -0,0 +1,325 @@
+/*	$NetBSD: netwalker_btn.c,v 1.1 2014/03/29 12:00:27 hkenken Exp $	*/
+
+/*
+ * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: netwalker_btn.c,v 1.1 2014/03/29 12:00:27 hkenken Exp $");
+
+#include "opt_imxspi.h"
+#include "opt_mousebtn.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/lock.h>
+#include <sys/callout.h>
+#include <sys/gpio.h>
+#include <sys/bus.h>
+#include <sys/mutex.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsmousevar.h>
+
+#include <dev/gpio/gpiovar.h>
+
+#define GPIO1_BASE		160
+
+#define MOUSEBTN_PIN_LEFT	0
+#define MOUSEBTN_PIN_RIGHT	1
+#define MOUSEBTN_NPINS		2
+
+#define POLLRATE (hz/10)
+
+struct mousebtn_softc
+{
+	device_t sc_dev;
+	void *sc_gpio;
+	void *sc_intr[MOUSEBTN_NPINS];
+
+	struct gpio_pinmap sc_map;
+	int sc_map_pins[MOUSEBTN_NPINS];
+
+	int sc_buttons;
+
+	struct callout sc_c;
+	kmutex_t sc_lock;
+
+	int sc_enabled;
+	struct device *sc_wsmousedev;
+};
+
+static int mousebtn_match(device_t, cfdata_t, void *);
+static void mousebtn_attach(device_t, device_t, void *);
+static int mousebtn_detach(device_t, int);
+
+CFATTACH_DECL_NEW(btn_netwalker, sizeof(struct mousebtn_softc),
+	mousebtn_match, mousebtn_attach, mousebtn_detach, NULL);
+
+static void mousebtn_poll(void *);
+static int mousebtn_intr(void *);
+
+static int mousebtn_enable(void *v);
+static void mousebtn_disable(void *v);
+static int mousebtn_ioctl(void *, u_long, void *, int, struct lwp *);
+
+static bool mousebtn_resume(device_t, const pmf_qual_t *);
+static bool mousebtn_suspend(device_t, const pmf_qual_t *);
+
+static const struct wsmouse_accessops mousebtn_accessops = {
+	.enable	 = mousebtn_enable,
+	.ioctl	 = mousebtn_ioctl,
+	.disable = mousebtn_disable
+};
+
+static int
+mousebtn_match(device_t parent, cfdata_t cf, void * aux)
+{
+	struct gpio_attach_args *ga = aux;
+
+	if (strcmp(ga->ga_dvname, cf->cf_name))
+		return 0;
+	if (ga->ga_offset == -1)
+		return 0;
+
+	/* check that we have enough pins */
+	if (gpio_npins(ga->ga_mask) != MOUSEBTN_NPINS) {
+		aprint_debug("%s: invalid pin mask 0x%02x\n", cf->cf_name,
+		    ga->ga_mask);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void
+mousebtn_attach(device_t parent, device_t self, void *aux)
+{
+	struct mousebtn_softc *sc = device_private(self);
+	struct gpio_attach_args *ga = aux;
+	int caps;
+	struct wsmousedev_attach_args a;
+
+	sc->sc_dev = self;
+	sc->sc_gpio = ga->ga_gpio;
+
+	/* map pins */
+	sc->sc_map.pm_map = sc->sc_map_pins;
+	if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
+		&sc->sc_map)) {
+		aprint_error(": couldn't map the pins\n");
+		return;
+	}
+
+	/* configure left pin */
+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, MOUSEBTN_PIN_LEFT);
+	if (!(caps & GPIO_PIN_INPUT)) {
+		aprint_error(": pin is unable to read input\n");
+		gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
+		return;
+	}
+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, MOUSEBTN_PIN_LEFT,
+	    GPIO_PIN_INPUT);
+
+	/* configure right pin */
+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, MOUSEBTN_PIN_RIGHT);
+	if (!(caps & GPIO_PIN_INPUT)) {
+		aprint_error(": pin is unable to read input\n");
+		gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
+		return;
+	}
+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, MOUSEBTN_PIN_RIGHT,
+	    GPIO_PIN_INPUT);
+
+	/* interrupt settings */
+	sc->sc_intr[0] = intr_establish(GPIO1_BASE + ga->ga_offset,
+	    IPL_VM, IST_EDGE_BOTH, mousebtn_intr, sc);
+	if (sc->sc_intr[0] == NULL) {
+		aprint_error(": couldn't establish interrupt\n");
+		return;
+	}
+	sc->sc_intr[1] = intr_establish(GPIO1_BASE + ga->ga_offset + 1,
+	     IPL_VM, IST_EDGE_BOTH, mousebtn_intr, sc);
+	if (sc->sc_intr[1] == NULL) {
+		aprint_error(": couldn't establish interrupt\n");
+		intr_disestablish(sc->sc_intr[0]);
+		return;
+	}
+
+	aprint_normal(": NetWalker mouse button\n");
+	aprint_naive(": NetWalker mouse button\n");
+
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+	callout_init(&sc->sc_c, 0);
+
+	a.accessops = &mousebtn_accessops;
+	a.accesscookie = sc;
+
+	sc->sc_buttons = 0;
+	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
+}
+
+static int
+mousebtn_detach(device_t self, int flags)
+{
+	struct mousebtn_softc *sc = device_private(self);
+
+	if (sc->sc_intr[0] != NULL)
+		intr_disestablish(sc->sc_intr[0]);
+	if (sc->sc_intr[1] != NULL)
+		intr_disestablish(sc->sc_intr[1]);
+
+	gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
+
+	return 0;
+}
+
+static void
+mousebtn_poll(void *arg)
+{
+	struct mousebtn_softc *sc = (struct mousebtn_softc *)arg;
+	uint32_t buttons = 0;
+	int s;
+	int left;
+	int right;
+
+	mutex_enter(&sc->sc_lock);
+
+	left = !gpio_pin_read(sc->sc_gpio, &sc->sc_map, MOUSEBTN_PIN_LEFT);
+	right = !gpio_pin_read(sc->sc_gpio, &sc->sc_map, MOUSEBTN_PIN_RIGHT);
+	buttons = (right << 2) | left;
+
+	if (sc->sc_buttons != buttons) {
+		s = spltty();
+		wsmouse_input(sc->sc_wsmousedev, buttons, 0, 0, 0, 0,
+		    WSMOUSE_INPUT_DELTA);
+		sc->sc_buttons = buttons;
+		splx(s);
+	}
+
+	mutex_exit(&sc->sc_lock);
+
+#if defined(MOUSEBTN_POLLING)
+	if (sc->sc_enabled)
+		callout_reset(&sc->sc_c, POLLRATE, mousebtn_poll, sc);
+#endif
+	return;
+}
+
+static int
+mousebtn_intr(void *v)
+{
+	struct mousebtn_softc *sc = v;
+
+	if (sc->sc_enabled)
+		callout_reset(&sc->sc_c, POLLRATE, mousebtn_poll, sc);
+
+	return 1;
+}
+
+
+int
+mousebtn_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
+{
+	struct wsmouse_id *id;
+
+	switch (cmd) {
+	case WSMOUSEIO_GTYPE:
+		*(u_int *)data = WSMOUSE_TYPE_PS2;
+		return 0;
+	case WSMOUSEIO_GETID:
+		id = (struct wsmouse_id *)data;
+		if (id->type != WSMOUSE_ID_TYPE_UIDSTR)
+			return EINVAL;
+		strlcpy(id->data, "NetWalker Mouse Button", WSMOUSE_ID_MAXLEN);
+		id->length = strlen(id->data);
+		return 0;
+	}
+
+	return EPASSTHROUGH;
+}
+
+int
+mousebtn_enable(void *v)
+{
+	struct mousebtn_softc *sc = (struct mousebtn_softc *)v;
+
+	if (sc->sc_enabled)
+		return EBUSY;
+
+	if (!pmf_device_register(sc->sc_dev, mousebtn_suspend, mousebtn_resume))
+		aprint_error_dev(sc->sc_dev,
+		    "couldn't establish power handler\n");
+
+	sc->sc_enabled = 1;
+#if defined(MOUSEBTN_POLLING)
+	callout_reset(&sc->sc_c, POLLRATE, mousebtn_poll, sc);
+#endif
+
+	return 0;
+}
+
+void
+mousebtn_disable(void *v)
+{
+	struct mousebtn_softc *sc = (struct mousebtn_softc *)v;
+
+	if (!sc->sc_enabled)
+		return;
+
+	pmf_device_deregister(sc->sc_dev);
+
+	sc->sc_enabled = 0;
+
+	return;
+}
+
+static bool
+mousebtn_suspend(device_t dv, const pmf_qual_t *qual)
+{
+	struct mousebtn_softc *sc = device_private(dv);
+
+#if defined(MOUSEBTN_POLLING)
+	callout_stop(&sc->sc_c);
+#endif
+	sc->sc_enabled = 0;
+
+	return true;
+}
+
+static bool
+mousebtn_resume(device_t dv, const pmf_qual_t *qual)
+{
+	struct mousebtn_softc *sc = device_private(dv);
+
+	sc->sc_enabled = 1;
+#if defined(MOUSEBTN_POLLING)
+	callout_reset(&sc->sc_c, POLLRATE, mousebtn_poll, sc);
+#endif
+	return true;
+}
+
Index: src/sys/arch/evbarm/netwalker/netwalker_spi.c
diff -u /dev/null src/sys/arch/evbarm/netwalker/netwalker_spi.c:1.1
--- /dev/null	Sat Mar 29 12:00:27 2014
+++ src/sys/arch/evbarm/netwalker/netwalker_spi.c	Sat Mar 29 12:00:27 2014
@@ -0,0 +1,152 @@
+/*	$NetBSD: netwalker_spi.c,v 1.1 2014/03/29 12:00:27 hkenken Exp $	*/
+
+/*-
+ * Copyright (c) 2009  Genetec Corporation.  All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: netwalker_spi.c,v 1.1 2014/03/29 12:00:27 hkenken Exp $");
+
+#include "opt_imxspi.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+
+#include <arm/imx/imx51reg.h>
+#include <arm/imx/imx51var.h>
+#include <arm/imx/imx51_ccmvar.h>
+#include <arm/imx/imx51_ccmreg.h>
+#include <arm/imx/imx51_iomuxreg.h>
+#include <arm/imx/imxgpiovar.h>
+#include <arm/imx/imxspivar.h>
+
+struct imx51spi_softc {
+	struct imxspi_softc	sc_spi;
+	struct spi_chipset_tag	sc_tag;
+};
+
+CFATTACH_DECL_NEW(spi_netwalker, sizeof(struct imx51spi_softc),
+    imxspi_match, imxspi_attach, NULL, NULL);
+
+static int
+imxspi_cs_enable(void *arg, int slave)
+{
+	switch (slave) {
+	case 0:
+		gpio_data_write(GPIO_NO(4, 24), 0);
+		gpio_set_direction(GPIO_NO(4, 24), GPIO_DIR_OUT);
+		break;
+	case 1:
+		gpio_data_write(GPIO_NO(4, 25), 0);
+		gpio_set_direction(GPIO_NO(4, 25), GPIO_DIR_OUT);
+		break;
+	case 2:
+		gpio_data_write(GPIO_NO(3, 0), 0);
+		gpio_set_direction(GPIO_NO(3, 0), GPIO_DIR_OUT);
+		break;
+	}
+
+	return 0;
+}
+
+static int
+imxspi_cs_disable(void *arg, int slave)
+{
+	switch (slave) {
+	case 0:
+		gpio_data_write(GPIO_NO(4, 24), 1);
+		gpio_set_direction(GPIO_NO(4, 24), GPIO_DIR_IN);
+		break;
+	case 1:
+		gpio_data_write(GPIO_NO(4, 25), 1);
+		gpio_set_direction(GPIO_NO(4, 25), GPIO_DIR_IN);
+		break;
+	case 2:
+		gpio_data_write(GPIO_NO(3, 0), 1);
+		gpio_set_direction(GPIO_NO(3, 0), GPIO_DIR_IN);
+		break;
+	}
+
+	return 0;
+}
+
+int
+imxspi_match(device_t parent, cfdata_t cf, void *aux)
+{
+	if (strcmp(cf->cf_name, "imxspi") == 0)
+		return 1;
+	if (cf->cf_unit != 0)
+		return 1;
+
+	return 0;
+}
+
+void
+imxspi_attach(device_t parent, device_t self, void *aux)
+{
+	struct imx51spi_softc *sc = device_private(self);
+	struct axi_attach_args *aa = aux;
+	struct imxspi_attach_args saa;
+	int cf_flags = device_cfdata(self)->cf_flags;
+
+	sc->sc_tag.cookie = sc;
+
+	if (device_cfdata(self)->cf_unit == 0) {
+		/* CS 0 GPIO setting */
+		gpio_data_write(GPIO_NO(4, 24), 1);
+		gpio_set_direction(GPIO_NO(4, 24), GPIO_DIR_IN);
+
+		/* CS 1 GPIO setting */
+		gpio_data_write(GPIO_NO(4, 25), 1);
+		gpio_set_direction(GPIO_NO(4, 25), GPIO_DIR_IN);
+
+		/* CS 2 */
+		/* OJ6SH-T25 Shutdown */
+		gpio_data_write(GPIO_NO(3, 14), 0);
+		gpio_set_direction(GPIO_NO(3, 14), GPIO_DIR_OUT);
+
+		/* CS 2 GPIO setting */
+		gpio_data_write(GPIO_NO(3, 0), 1);
+		gpio_set_direction(GPIO_NO(3, 0), GPIO_DIR_IN);
+
+		sc->sc_tag.spi_cs_enable = imxspi_cs_enable;
+		sc->sc_tag.spi_cs_disable = imxspi_cs_disable;
+	}
+
+	saa.saa_iot = aa->aa_iot;
+	saa.saa_addr = aa->aa_addr;
+	saa.saa_size = aa->aa_size;
+	saa.saa_irq = aa->aa_irq;
+	saa.saa_enhanced = cf_flags;
+
+	saa.saa_nslaves = IMXSPINSLAVES;
+	saa.saa_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT);
+	saa.saa_tag = &sc->sc_tag;
+
+	sc->sc_spi.sc_dev = self;
+
+	imxspi_attach_common(parent, &sc->sc_spi, &saa);
+}

Index: src/sys/dev/spi/oj6sh.c
diff -u /dev/null src/sys/dev/spi/oj6sh.c:1.1
--- /dev/null	Sat Mar 29 12:00:27 2014
+++ src/sys/dev/spi/oj6sh.c	Sat Mar 29 12:00:27 2014
@@ -0,0 +1,379 @@
+/*	$NetBSD: oj6sh.c,v 1.1 2014/03/29 12:00:27 hkenken Exp $	*/
+
+/*
+ * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+/*
+ * Sharp NetWalker's Optical Joystick
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: oj6sh.c,v 1.1 2014/03/29 12:00:27 hkenken Exp $");
+
+#include "opt_oj6sh.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/lock.h>
+#include <sys/callout.h>
+#include <sys/bus.h>
+#include <sys/mutex.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsmousevar.h>
+#include <dev/wscons/wsdisplayvar.h>
+
+#include <dev/hpc/hpcfbio.h>
+#include <dev/hpc/hpctpanelvar.h>
+
+#include <dev/spi/spivar.h>
+
+#ifdef OJ6SH_DEBUG
+int oj6sh_debug = OJ6SH_DEBUG;
+#define DPRINTF(n,x)	if (oj6sh_debug>(n)) printf x;
+#else
+#define DPRINTF(n,x)
+#endif
+
+#define POLLRATE (hz/30)
+
+/* register address */
+#define OJ6SH_PRODUCT		0x00
+#define OJ6SH_REVISION		0x01
+#define OJ6SH_MOTION		0x02
+#define OJ6SH_DELTA_X		0x03
+#define OJ6SH_DELTA_Y		0x04
+#define OJ6SH_SQUAL		0x05
+#define OJ6SH_SHUTTER		0x06
+#define OJ6SH_CONFIG		0x11
+#define OJ6SH_RESET		0x3a
+#define  POWERON_RESET		0x5a
+#define OJ6SH_N_REVISION	0x3e
+#define OJ6SH_N_PRODUCT		0x3f
+
+struct oj6sh_softc {
+	device_t sc_dev;
+
+	struct spi_handle *sc_sh;
+	struct callout sc_c;
+
+	kmutex_t sc_lock;
+	int sc_enabled;
+
+	device_t sc_wsmousedev;
+};
+
+struct oj6sh_delta {
+	int x;
+	int y;
+};
+
+static uint8_t oj6sh_read(struct spi_handle *, uint8_t);
+static void oj6sh_write(struct spi_handle *, uint8_t, uint8_t);
+
+static int oj6sh_match(device_t , cfdata_t , void *);
+static void oj6sh_attach(device_t , device_t , void *);
+
+CFATTACH_DECL_NEW(oj6sh, sizeof(struct oj6sh_softc),
+    oj6sh_match, oj6sh_attach, NULL, NULL);
+
+static bool oj6sh_motion(struct spi_handle *);
+static bool oj6sh_squal(struct spi_handle *);
+static bool oj6sh_shuttrer(struct spi_handle *);
+static int oj6sh_readdelta(struct spi_handle *, struct oj6sh_delta *);
+
+static void oj6sh_poll(void *);
+static int oj6sh_enable(void *v);
+static void oj6sh_disable(void *v);
+static int oj6sh_ioctl(void *, u_long, void *, int, struct lwp *);
+
+static bool oj6sh_resume(device_t, const pmf_qual_t *);
+static bool oj6sh_suspend(device_t, const pmf_qual_t *);
+
+static const struct wsmouse_accessops oj6sh_accessops = {
+	.enable = oj6sh_enable,
+	.ioctl = oj6sh_ioctl,
+	.disable = oj6sh_disable
+};
+
+static int
+oj6sh_match(device_t parent, cfdata_t match, void *aux)
+{
+	struct spi_attach_args *sa = aux;
+
+	if (strcmp(match->cf_name, "oj6sh"))
+		return 0;
+	if (spi_configure(sa->sa_handle, SPI_MODE_0, 2500000))
+		return 0;
+
+	return 2;
+}
+
+static void
+oj6sh_doattach(device_t self)
+{
+	struct oj6sh_softc *sc = device_private(self);
+	uint8_t product;
+	uint8_t rev;
+	uint8_t product_inv;
+	uint8_t rev_inv;
+
+	/* reset */
+	oj6sh_write(sc->sc_sh, OJ6SH_RESET, POWERON_RESET);
+	delay(10000);
+
+	/* resolution */
+	oj6sh_write(sc->sc_sh, OJ6SH_CONFIG, 0x80);
+
+	product = oj6sh_read(sc->sc_sh, OJ6SH_PRODUCT);
+	rev = oj6sh_read(sc->sc_sh, OJ6SH_REVISION);
+	product_inv = oj6sh_read(sc->sc_sh, OJ6SH_N_PRODUCT);
+	rev_inv = oj6sh_read(sc->sc_sh, OJ6SH_N_REVISION);
+
+	if (((product | product_inv) != 0xff) || ((rev | rev_inv) != 0xff)) {
+		aprint_error_dev(self,
+		    "mismatch product (%02x:%02x), rev (%02x:%02x)\n",
+		    product, product_inv, rev, rev_inv);
+		return;
+	}
+
+	aprint_normal("%s: id 0x%02x, revision 0x%02x\n",
+	    device_xname(sc->sc_dev), product, rev);
+
+	return;
+}
+
+static void
+oj6sh_attach(device_t parent, device_t self, void *aux)
+{
+	struct oj6sh_softc *sc = device_private(self);
+	struct spi_attach_args *sa = aux;
+	struct wsmousedev_attach_args a;
+
+	aprint_normal(": OJ6SH-T25 Optical Joystick\n");
+
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+
+	sc->sc_dev = self;
+	sc->sc_enabled = 0;
+
+	callout_init(&sc->sc_c, 0);
+
+	sc->sc_sh = sa->sa_handle;
+
+	a.accessops = &oj6sh_accessops;
+	a.accesscookie = sc;
+
+	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
+
+	config_interrupts(self, oj6sh_doattach);
+}
+
+static void
+oj6sh_poll(void *arg)
+{
+	struct oj6sh_softc *sc = (struct oj6sh_softc *)arg;
+	struct oj6sh_delta delta = {0, 0};
+	uint32_t buttons = 0;
+	int s;
+	int x, y;
+
+	mutex_enter(&sc->sc_lock);
+
+	if (oj6sh_motion(sc->sc_sh) == false)
+		goto out;
+	else if ((oj6sh_squal(sc->sc_sh) == true) &&
+	    (oj6sh_shuttrer(sc->sc_sh) == true))
+		goto out;
+
+	oj6sh_readdelta(sc->sc_sh, &delta);
+	DPRINTF(3,("%s: x = %d, y = %d\n", device_xname(sc->sc_dev),
+		delta.x, delta.y));
+
+#if defined(J6SH_DOWN_Y_LEFT_X)
+	y = -delta.y;
+	x = -delta.x;
+#elif defined(OJ6SH_UP_X_LEFT_Y)
+	y = delta.x;
+	x = -delta.y;
+#elif defined(OJ6SH_DOWN_X_RIGHT_Y)
+	y = -delta.x;
+	x = delta.y;
+#else /* OJ6SH_UP_Y_RIGHT_X */
+	y = delta.y;
+	x = delta.x;
+#endif
+	s = spltty();
+	wsmouse_input(sc->sc_wsmousedev, buttons, x, y, 0, 0,
+	    WSMOUSE_INPUT_DELTA);
+	splx(s);
+out:
+	mutex_exit(&sc->sc_lock);
+
+	if (sc->sc_enabled)
+		callout_reset(&sc->sc_c, POLLRATE, oj6sh_poll, sc);
+
+	return;
+}
+
+static uint8_t
+oj6sh_read(struct spi_handle *spi, uint8_t reg)
+{
+	uint8_t ret = 0;
+
+	spi_send_recv(spi, 1, &reg, 1, &ret);
+	DPRINTF(4,("%s: 0x%02x = 0x%02x\n", __func__, reg, ret));
+	return ret;
+}
+
+static void
+oj6sh_write(struct spi_handle *spi, uint8_t reg, uint8_t val)
+{
+	uint8_t tmp[2] = {reg | 0x80, val};
+
+	spi_send(spi, 2, tmp);
+	DPRINTF(4,("%s: 0x%02x = 0x%02x\n", __func__, reg, val));
+	return;
+}
+
+static bool
+oj6sh_motion(struct spi_handle *spi)
+{
+	uint16_t motion;
+	motion = oj6sh_read(spi, OJ6SH_MOTION);
+	return (motion & __BIT(7) ? true : false);
+}
+
+static bool
+oj6sh_squal(struct spi_handle *spi)
+{
+	uint16_t squal;
+	squal = oj6sh_read(spi, OJ6SH_SQUAL);
+	return (squal < 25 ? true : false);
+}
+
+static bool
+oj6sh_shuttrer(struct spi_handle *spi)
+{
+	uint16_t shutter;
+	shutter = oj6sh_read(spi, OJ6SH_SHUTTER) << 8;
+	shutter |= oj6sh_read(spi, OJ6SH_SHUTTER + 1);
+	return (shutter > 600 ? true : false);
+}
+
+static int
+oj6sh_readdelta(struct spi_handle *spi, struct oj6sh_delta *delta)
+{
+	delta->x = (int8_t)oj6sh_read(spi, OJ6SH_DELTA_X);
+	delta->y = (int8_t)oj6sh_read(spi, OJ6SH_DELTA_Y);
+	return 0;
+}
+
+int
+oj6sh_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
+{
+	struct wsmouse_id *id;
+
+	switch (cmd) {
+	case WSMOUSEIO_GTYPE:
+		*(u_int *)data = WSMOUSE_TYPE_PS2;
+		return 0;
+	case WSMOUSEIO_GETID:
+		id = (struct wsmouse_id *)data;
+		if (id->type != WSMOUSE_ID_TYPE_UIDSTR)
+			return EINVAL;
+		strlcpy(id->data, "OJ6SH-T25", WSMOUSE_ID_MAXLEN);
+		id->length = strlen(id->data);
+		return 0;
+	}
+
+	return EPASSTHROUGH;
+}
+
+int
+oj6sh_enable(void *v)
+{
+	struct oj6sh_softc *sc = (struct oj6sh_softc *)v;
+
+	DPRINTF(3,("%s: oj6sh_enable()\n", device_xname(sc->sc_dev)));
+	if (sc->sc_enabled) {
+		DPRINTF(3,("%s: already enabled\n", device_xname(sc->sc_dev)));
+		return EBUSY;
+	}
+
+	if (!pmf_device_register(sc->sc_dev, oj6sh_suspend, oj6sh_resume))
+		aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n");
+
+	sc->sc_enabled = 1;
+	callout_reset(&sc->sc_c, POLLRATE, oj6sh_poll, sc);
+
+	return 0;
+}
+
+void
+oj6sh_disable(void *v)
+{
+	struct oj6sh_softc *sc = (struct oj6sh_softc *)v;
+
+	DPRINTF(3,("%s: oj6sh_disable()\n", device_xname(sc->sc_dev)));
+	if (!sc->sc_enabled) {
+		DPRINTF(3,("%s: already disabled()\n", device_xname(sc->sc_dev)));
+		return;
+	}
+
+	pmf_device_deregister(sc->sc_dev);
+
+	sc->sc_enabled = 0;
+
+	return;
+}
+
+static bool
+oj6sh_suspend(device_t dv, const pmf_qual_t *qual)
+{
+	struct oj6sh_softc *sc = device_private(dv);
+
+	DPRINTF(3,("%s: oj6sh_suspend()\n", device_xname(sc->sc_dev)));
+	callout_stop(&sc->sc_c);
+	sc->sc_enabled = 0;
+
+	return true;
+}
+
+static bool
+oj6sh_resume(device_t dv, const pmf_qual_t *qual)
+{
+	struct oj6sh_softc *sc = device_private(dv);
+
+	DPRINTF(3,("%s: oj6sh_resume()\n", device_xname(sc->sc_dev)));
+	sc->sc_enabled = 1;
+	callout_reset(&sc->sc_c, POLLRATE, oj6sh_poll, sc);
+
+	return true;
+}
+

Reply via email to