apu1c led driver
Larry Baird
lab at gta.com
Tue Apr 22 02:07:52 UTC 2014
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 at gta.com | TEL 407-380-0220
More information about the freebsd-hackers
mailing list