Module Name: src Committed By: khorben Date: Wed Apr 17 01:06:14 UTC 2013
Modified Files: src/sys/arch/evbarm/conf: N900 files.n900 Added Files: src/sys/arch/evbarm/n900: n900_lckbtn.c Log Message: Imported n900lckbtn(4), a driver for the lock button on the Nokia N900 smartphone. Currently reporting events via a hotkey, named after the driver instance. Tasted and approved. To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/arch/evbarm/conf/N900 cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/conf/files.n900 cvs rdiff -u -r0 -r1.1 src/sys/arch/evbarm/n900/n900_lckbtn.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/evbarm/conf/N900 diff -u src/sys/arch/evbarm/conf/N900:1.9 src/sys/arch/evbarm/conf/N900:1.10 --- src/sys/arch/evbarm/conf/N900:1.9 Wed Apr 17 00:57:22 2013 +++ src/sys/arch/evbarm/conf/N900 Wed Apr 17 01:06:13 2013 @@ -1,5 +1,5 @@ # -# $NetBSD: N900,v 1.9 2013/04/17 00:57:22 khorben Exp $ +# $NetBSD: N900,v 1.10 2013/04/17 01:06:13 khorben Exp $ # # N900 -- Nokia N900 Kernel # @@ -205,9 +205,9 @@ flash2 at nand0 offset 0x3a02040 size 0 # Interrupt Controller omapicu0 at obio0 addr 0x48200000 size 0x1000 intrbase 0 omapgpio0 at obio1 addr 0x48310000 size 0x0400 intrbase 96 intr 29 -#omapgpio1 at obio2 addr 0x49050000 size 0x0400 intrbase 128 intr 30 -#omapgpio2 at obio2 addr 0x49052000 size 0x0400 intrbase 160 intr 31 -#omapgpio3 at obio2 addr 0x49054000 size 0x0400 intrbase 192 intr 32 +omapgpio1 at obio2 addr 0x49050000 size 0x0400 intrbase 128 intr 30 +omapgpio2 at obio2 addr 0x49052000 size 0x0400 intrbase 160 intr 31 +omapgpio3 at obio2 addr 0x49054000 size 0x0400 intrbase 192 intr 32 omapgpio4 at obio2 addr 0x49056000 size 0x0400 intrbase 224 intr 33 #omapgpio5 at obio2 addr 0x49058000 size 0x0400 intrbase 256 intr 34 @@ -217,6 +217,9 @@ gpio* at omapgpio? # Charging sensor n900acad0 at gpio0 offset 7 mask 0x1 #intr 103 +# Lock button +n900lckbtn0 at gpio3 offset 17 mask 0x1 #intr 209 + # System Control Module omapscm0 at obio0 addr 0x48002000 size 0x1000 Index: src/sys/arch/evbarm/conf/files.n900 diff -u src/sys/arch/evbarm/conf/files.n900:1.2 src/sys/arch/evbarm/conf/files.n900:1.3 --- src/sys/arch/evbarm/conf/files.n900:1.2 Sun Apr 14 19:17:06 2013 +++ src/sys/arch/evbarm/conf/files.n900 Wed Apr 17 01:06:14 2013 @@ -1,4 +1,4 @@ -# $NetBSD: files.n900,v 1.2 2013/04/14 19:17:06 khorben Exp $ +# $NetBSD: files.n900,v 1.3 2013/04/17 01:06:14 khorben Exp $ # # Nokia N900 configuration info # @@ -24,3 +24,8 @@ defparam opt_com.h CONSADDR CONSPEED device n900acad: sysmon_envsys attach n900acad at gpio with n900acad file arch/evbarm/n900/n900_acad.c n900acad + +# Lock button +device n900lckbtn: sysmon_envsys +attach n900lckbtn at gpio with n900lckbtn +file arch/evbarm/n900/n900_lckbtn.c n900lckbtn Added files: Index: src/sys/arch/evbarm/n900/n900_lckbtn.c diff -u /dev/null src/sys/arch/evbarm/n900/n900_lckbtn.c:1.1 --- /dev/null Wed Apr 17 01:06:14 2013 +++ src/sys/arch/evbarm/n900/n900_lckbtn.c Wed Apr 17 01:06:14 2013 @@ -0,0 +1,194 @@ +/* $NetBSD: n900_lckbtn.c,v 1.1 2013/04/17 01:06:14 khorben Exp $ */ + +/* + * Lock button driver for the Nokia N900. + * + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Pierre Pronchery (khor...@defora.org). + * + * 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: n900_lckbtn.c,v 1.1 2013/04/17 01:06:14 khorben Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/gpio.h> + +#include <dev/gpio/gpiovar.h> +#include <dev/sysmon/sysmonvar.h> + +#include <arm/omap/omap2_gpio.h> + + +/* The base interrupt for the corresponding GPIO device where this driver + * attaches. This is an ugly workaround the current limitations of gpio(4), + * which does not seem to allow a better way to locate the interrupt yet. */ +#define N900LCKBTN_GPIO_BASE 192 + +#define N900LCKBTN_PIN_INPUT 0 +#define N900LCKBTN_NPINS 1 + + +struct n900lckbtn_softc +{ + device_t sc_dev; + void * sc_gpio; + void * sc_intr; + + struct gpio_pinmap sc_map; + int sc_map_pins[N900LCKBTN_NPINS]; + + struct sysmon_pswitch sc_smpsw; + int sc_event; +}; + +static int n900lckbtn_match(device_t, cfdata_t, void *); +static void n900lckbtn_attach(device_t, device_t, void *); +static int n900lckbtn_detach(device_t, int); + +CFATTACH_DECL_NEW(n900lckbtn, sizeof(struct n900lckbtn_softc), + n900lckbtn_match, n900lckbtn_attach, n900lckbtn_detach, NULL); + +static void n900lckbtn_refresh(struct n900lckbtn_softc *); + +static int n900lckbtn_intr(void *v); + + +static int +n900lckbtn_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) != N900LCKBTN_NPINS) { + aprint_debug("%s: invalid pin mask 0x%02x\n", cf->cf_name, + ga->ga_mask); + return 0; + } + + return 1; +} + +static void +n900lckbtn_attach(device_t parent, device_t self, void *aux) +{ + struct n900lckbtn_softc *sc = device_private(self); + struct gpio_attach_args *ga = aux; + int caps; + + 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(": could not map the pins\n"); + return; + } + + /* configure the input pin */ + caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, N900LCKBTN_PIN_INPUT); + 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, N900LCKBTN_PIN_INPUT, + GPIO_PIN_INPUT); + + sc->sc_intr = intr_establish(N900LCKBTN_GPIO_BASE + ga->ga_offset, + IST_EDGE_BOTH, IPL_VM, n900lckbtn_intr, sc); + if (sc->sc_intr == NULL) { + aprint_error(": could not establish interrupt\n"); + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); + return; + } + + aprint_normal(": N900 lock button\n"); + aprint_naive(": N900 lock button\n"); + + if (!pmf_device_register(sc->sc_dev, NULL, NULL)) { + aprint_error_dev(sc->sc_dev, + "could not establish power handler\n"); + } + + sc->sc_smpsw.smpsw_name = device_xname(self); + sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_HOTKEY; + sc->sc_event = PSWITCH_EVENT_RELEASED; + sysmon_pswitch_register(&sc->sc_smpsw); +} + +static int +n900lckbtn_detach(device_t self, int flags) +{ + struct n900lckbtn_softc *sc = device_private(self); + + if (sc->sc_intr != NULL) { + intr_disestablish(sc->sc_intr); + } + + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); + pmf_device_deregister(self); + + return 0; +} + +static int +n900lckbtn_intr(void *v) +{ + struct n900lckbtn_softc *sc = v; + + n900lckbtn_refresh(sc); + return 1; +} + +static void +n900lckbtn_refresh(struct n900lckbtn_softc *sc) +{ + int i; + int event; + + i = gpio_pin_read(sc->sc_gpio, &sc->sc_map, N900LCKBTN_PIN_INPUT); + event = (i == GPIO_PIN_HIGH) + ? PSWITCH_EVENT_RELEASED : PSWITCH_EVENT_PRESSED; + + /* crude way to avoid duplicate events */ + if(event == sc->sc_event) + return; + sc->sc_event = event; + + /* report the event */ + sysmon_pswitch_event(&sc->sc_smpsw, event); +}