Date: Mon, 21 Apr 2014 22:01:09 -0400 From: Larry Baird <lab@gta.com> To: freebsd-hackers@freebsd.org Subject: apu1c led driver Message-ID: <20140422020109.GA57760@gta.com>
next in thread | raw e-mail | index | archive | help
There exists a nice simple linux driver for the leds on a pc engines apu1c board at http://daduke.org/linux/apu/. Converting driver to use led(4) and run on FreeBSD seemed straight forward. Or that is until I realized I don't know how to alloc and write to a fixed set of I/O ports. I believe the magic happens by using bus_alloc_resource(). Code below attempts to allow control of the second of three leds on the apu1c board. Once I get that working, it should be easy to extend driver to support all three leds. What is the correct way to allocate and write to a a set of I/O ports at address 0xFED801BD? #include <sys/param.h> #include <sys/bus.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/rman.h> #include <x86/bus.h> #include <dev/led/led.h> #define BASEADDR (0xFED801BD) #define LEDON (0x8) #define LEDOFF (0xC8) #define GPIO_187 187 // MODESW #define GPIO_189 189 // LED1# #define GPIO_190 190 // LED2# #define GPIO_191 191 // LED3# struct apuled_softc { device_t sc_dev; int sc_rid; int sc_type; int sc_offset; struct resource *sc_res; void *sc_led1; }; /* * Device methods. */ static int apuled_probe(device_t dev); static int apuled_attach(device_t dev); static int apuled_detach(device_t dev); static device_method_t apuled_methods[] = { /* Device interface */ DEVMETHOD(device_probe, apuled_probe), DEVMETHOD(device_attach, apuled_attach), DEVMETHOD(device_detach, apuled_detach), DEVMETHOD_END }; static driver_t apuled_driver = { "apuled", apuled_methods, sizeof(struct apuled_softc), }; static devclass_t apuled_devclass; DRIVER_MODULE(apuled, pci, apuled_driver, apuled_devclass, NULL, NULL); static int apuled_probe(device_t dev) { device_set_desc(dev, "APU led"); return (BUS_PROBE_GENERIC); } static void led_func(void *ptr, int onoff) { struct apuled_softc *sc = (struct apuled_softc *)ptr; u_int8_t value; if ( onoff ) { value = LEDON; } else { value = LEDOFF; } bus_write_1(sc->sc_res, 1, value); } static int apuled_attach(device_t dev) { struct apuled_softc *sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_rid = 1; sc->sc_type = SYS_RES_IOPORT; if ( (sc->sc_res = bus_alloc_resource( sc->sc_dev, sc->sc_type, &sc->sc_rid, BASEADDR, BASEADDR + 4, 4, RF_ACTIVE)) == NULL ) { device_printf( sc->sc_dev, "Unable to allocate bus resource\n" ); return ENXIO; } else if ( (sc->sc_led1 = led_create(led_func, sc, "led1")) == NULL ) { device_printf( sc->sc_dev, "Unable to create LED 1\n" ); return ENXIO; } else { device_printf( sc->sc_dev, "LED 1 created\n" ); } return (0); } int apuled_detach(device_t dev) { struct apuled_softc *sc = device_get_softc(dev); if ( sc->sc_led1 != NULL ) { led_destroy( sc->sc_led1 ); } if ( sc->sc_res != NULL ) { bus_release_resource( sc->sc_dev, sc->sc_type, sc->sc_rid, sc->sc_res ); } return (0); } -- ------------------------------------------------------------------------ Larry Baird Global Technology Associates, Inc. 1992-2012 | http://www.gta.com Celebrating Twenty Years of Software Innovation | Orlando, FL Email: lab@gta.com | TEL 407-380-0220
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140422020109.GA57760>