Date: Fri, 8 May 2009 15:22:10 +0100 (BST) From: Gavin Atkinson <gavin@FreeBSD.org> To: FreeBSD-gnats-submit@FreeBSD.org Subject: arm/134368: [patch] nslu2_led driver for the LEDs on the NSLU2 Message-ID: <200905081422.n48EMArP073408@buffy.york.ac.uk> Resent-Message-ID: <200905081430.n48EU2rD066149@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 134368 >Category: arm >Synopsis: [patch] nslu2_led driver for the LEDs on the NSLU2 >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-arm >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri May 08 14:30:02 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Gavin Atkinson >Release: FreeBSD 7.1-STABLE amd64 >Organization: >Environment: System: FreeBSD buffy.york.ac.uk 7.1-STABLE FreeBSD 7.1-STABLE #5: Fri Feb 13 11:25:58 GMT 2009 root@buffy.york.ac.uk:/usr/obj/usr/src/sys/GENERIC amd64 >Description: Simple driver for the LEDs on the NSLU2. This uses the led(4) API and provides devices under /dev/led/ to set the state of the four LEDs. It also switches the power LED to green on boot and to amber on shutdown, like the original NSLU2 does. Note that this requires the GPIO locking changes submitted in PR arm/134338. I've also created a new "files.nslu2" and "std.nslu2" file, as I have drivers for the buttons and RTC to be submitted soon, so it makes sense to factor NSLU out from the avila config now. Written by myself, under the 2-clause BSD license. >How-To-Repeat: N/A >Fix: --- nslu2_led.diff begins here --- Index: sys/arm/conf/NSLU =================================================================== RCS file: /home/ncvs/src/sys/arm/conf/NSLU,v retrieving revision 1.6 diff -u -r1.6 NSLU --- sys/arm/conf/NSLU 23 Feb 2009 18:34:56 -0000 1.6 +++ sys/arm/conf/NSLU 8 May 2009 14:12:48 -0000 @@ -30,6 +30,7 @@ include "../xscale/ixp425/std.ixp425" # NB: memory mapping is defined in std.avila (see also comment above) include "../xscale/ixp425/std.avila" +include "../xscale/ixp425/std.nslu2" options XSCALE_CACHE_READ_WRITE_ALLOCATE #To statically compile in device wiring instead of /boot/device.hints hints "NSLU.hints" #Default places to look for devices. @@ -91,6 +92,8 @@ device ixpiic # I2C bus glue device ixpwdog # watchdog timer +device nslu2_led # NSLU2 LEDs + device npe # Network Processing Engine device npe_fw device firmware Index: sys/arm/conf/NSLU.hints =================================================================== RCS file: /home/ncvs/src/sys/arm/conf/NSLU.hints,v retrieving revision 1.2 diff -u -r1.2 NSLU.hints --- sys/arm/conf/NSLU.hints 6 May 2009 20:24:17 -0000 1.2 +++ sys/arm/conf/NSLU.hints 8 May 2009 13:14:07 -0000 @@ -34,5 +34,6 @@ #hint.xrtc.0.at="iicbus0" #hint.xrtc.0.addr=0xde # Slug LED +hint.nslu2_led.0.at="ixp0" # Slug button # Slug Buzzer --- /dev/null 2009-05-08 15:11:01.000000000 +0100 +++ sys/arm/xscale/ixp425/nslu2_led.c 2009-05-08 15:14:11.000000000 +0100 @@ -0,0 +1,232 @@ +/*- + * Copyright (c) 2009, Gavin Atkinson <gavin@FreeBSD.org> + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> + +#include <sys/bus.h> +#include <sys/eventhandler.h> +#include <sys/lock.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/systm.h> + +#include <arm/xscale/ixp425/ixp425reg.h> +#include <arm/xscale/ixp425/ixp425var.h> + +#include <dev/led/led.h> + +#define GPIO_LED_STATUS_RED 0 +#define GPIO_LED_STATUS_GREEN 1 +#define GPIO_LED_DISK2 2 +#define GPIO_LED_DISK1 3 + +#define GPIO_LED_STATUS_RED_BIT (1U << GPIO_LED_STATUS_RED) +#define GPIO_LED_STATUS_GREEN_BIT (1U << GPIO_LED_STATUS_GREEN) +#define GPIO_LED_DISK2_BIT (1U << GPIO_LED_DISK2) +#define GPIO_LED_DISK1_BIT (1U << GPIO_LED_DISK1) + +/* Amber is produced by switching both red and green LEDs on */ +#define GPIO_LED_STATUS_AMBER_BITS (GPIO_LED_STATUS_RED_BIT | \ + GPIO_LED_STATUS_GREEN_BIT) + +#define GPIO_ALL_LED_BITS (GPIO_LED_STATUS_RED_BIT | \ + GPIO_LED_STATUS_GREEN_BIT | \ + GPIO_LED_DISK2_BIT | \ + GPIO_LED_DISK1_BIT) + +struct nslu2_led_softc { + device_t sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_gpio_ioh; + eventhandler_tag sc_shutdown_eh; + struct cdev *sc_srled; + struct cdev *sc_saled; + struct cdev *sc_sgled; + struct cdev *sc_d1led; + struct cdev *sc_d2led; +}; + +extern struct mtx ixp425_gpio_mtx; + +static void +nslu2_led_set(struct nslu2_led_softc *sc, int leds, int mask) +{ + uint32_t reg; + + /* On the NSLU2 hardware, a "1" written to the status LED outputs + * will switch the LEDs on, but for the disk LEDs a "1" switches + * them off. Handle that here, so the rest of the code doesn't + * have to deal with this detail. + */ + leds ^= (GPIO_LED_DISK1_BIT | GPIO_LED_DISK2_BIT); + + mtx_lock(&ixp425_gpio_mtx); + reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR); + reg &= ~mask; + reg |= (leds & mask); + GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg); + mtx_unlock(&ixp425_gpio_mtx); +} + +static void +nslu2_led_status_red_func(void *arg, int onoff) +{ + struct nslu2_led_softc *sc = arg; + + nslu2_led_set(sc, (onoff ? GPIO_LED_STATUS_RED_BIT : 0), + GPIO_LED_STATUS_RED_BIT); +} + +static void +nslu2_led_status_amber_func(void *arg, int onoff) +{ + struct nslu2_led_softc *sc = arg; + + /* XXX: Ideally this should be done through the led(4) interface, + * but there isn't currently a published interface to change + * state from the kernel, so we go behind led(4)'s back. + */ + nslu2_led_set(sc, (onoff ? GPIO_LED_STATUS_AMBER_BITS : 0), + GPIO_LED_STATUS_AMBER_BITS); +} + +static void +nslu2_led_status_green_func(void *arg, int onoff) +{ + struct nslu2_led_softc *sc = arg; + + nslu2_led_set(sc, (onoff ? GPIO_LED_STATUS_GREEN_BIT : 0), + GPIO_LED_STATUS_GREEN_BIT); +} + +static void +nslu2_led_status_disk1_func(void *arg, int onoff) +{ + struct nslu2_led_softc *sc = arg; + + nslu2_led_set(sc, (onoff ? GPIO_LED_DISK1_BIT : 0), + GPIO_LED_DISK1_BIT); +} + +static void +nslu2_led_status_disk2_func(void *arg, int onoff) +{ + struct nslu2_led_softc *sc = arg; + + nslu2_led_set(sc, (onoff ? GPIO_LED_DISK2_BIT : 0), + GPIO_LED_DISK2_BIT); +} + +static void +nslu2_led_shutdown(void *arg) +{ + struct nslu2_led_softc *sc = arg; + + EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_eh); + + /* Shutting down... Set status to amber */ + nslu2_led_set(sc, GPIO_LED_STATUS_AMBER_BITS, + GPIO_LED_STATUS_AMBER_BITS); +} + +static int +nslu2_led_probe(device_t dev) +{ + device_set_desc(dev, "NSLU2 LEDs"); + return (BUS_PROBE_DEFAULT); +} + +static int +nslu2_led_attach(device_t dev) +{ + struct nslu2_led_softc *sc = device_get_softc(dev); + struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); + + sc->sc_dev = dev; + sc->sc_iot = sa->sc_iot; + sc->sc_gpio_ioh = sa->sc_gpio_ioh; + + /* Configure LED GPIO pins as output */ + mtx_lock(&ixp425_gpio_mtx); + GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER, + GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER) &~ GPIO_ALL_LED_BITS); + mtx_unlock(&ixp425_gpio_mtx); + + /* Start with status LED green and disk LEDs off */ + sc->sc_srled = led_create_state(nslu2_led_status_red_func, + sc, "status-red", 0); + sc->sc_saled = led_create_state(nslu2_led_status_amber_func, + sc, "status-amber", 0); + sc->sc_sgled = led_create_state(nslu2_led_status_green_func, + sc, "status-green", 1); + sc->sc_d1led = led_create_state(nslu2_led_status_disk1_func, + sc, "disk1", 0); + sc->sc_d2led = led_create_state(nslu2_led_status_disk2_func, + sc, "disk2", 0); + + sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, + nslu2_led_shutdown, sc, SHUTDOWN_PRI_FIRST); + return (0); +} + +static void +nslu2_led_detach(device_t dev) +{ + struct nslu2_led_softc *sc = device_get_softc(dev); + + if (sc->sc_shutdown_eh) + EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_eh); + if (sc->sc_srled != NULL) + led_destroy(sc->sc_srled); + if (sc->sc_saled != NULL) + led_destroy(sc->sc_saled); + if (sc->sc_sgled != NULL) + led_destroy(sc->sc_sgled); + if (sc->sc_d1led != NULL) + led_destroy(sc->sc_d1led); + if (sc->sc_d2led != NULL) + led_destroy(sc->sc_d2led); +} + +static device_method_t nslu2_led_methods[] = { + DEVMETHOD(device_probe, nslu2_led_probe), + DEVMETHOD(device_attach, nslu2_led_attach), + DEVMETHOD(device_detach, nslu2_led_detach), + + {0, 0}, +}; + +static driver_t nslu2_led_driver = { + "nslu2_led", + nslu2_led_methods, + sizeof(struct nslu2_led_softc), +}; +static devclass_t nslu2_led_devclass; + +DRIVER_MODULE(nslu2_led, ixp, nslu2_led_driver, nslu2_led_devclass, 0, 0); --- /dev/null 2009-05-08 15:11:01.000000000 +0100 +++ sys/arm/xscale/ixp425/std.nslu2 2009-05-08 14:14:50.000000000 +0100 @@ -0,0 +1,7 @@ +#$FreeBSD$ + +# +# Linksys NSLU2 board configuration +# +files "../xscale/ixp425/files.nslu2" +# --- /dev/null 2009-05-08 15:11:01.000000000 +0100 +++ sys/arm/xscale/ixp425/files.nslu2 2009-05-08 14:14:55.000000000 +0100 @@ -0,0 +1,2 @@ +#$FreeBSD$ +arm/xscale/ixp425/nslu2_led.c optional nslu2_led --- nslu2_led.diff ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905081422.n48EMArP073408>