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, ®, 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; +} +