From owner-freebsd-hackers@FreeBSD.ORG Tue Apr 22 14:40:39 2014 Return-Path: Delivered-To: freebsd-hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9DE57992 for ; Tue, 22 Apr 2014 14:40:39 +0000 (UTC) Received: from mho-02-ewr.mailhop.org (mho-02-ewr.mailhop.org [204.13.248.72]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 606031DD7 for ; Tue, 22 Apr 2014 14:40:39 +0000 (UTC) Received: from c-24-8-230-52.hsd1.co.comcast.net ([24.8.230.52] helo=damnhippie.dyndns.org) by mho-02-ewr.mailhop.org with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.72) (envelope-from ) id 1Wcbs8-000PIs-5p; Tue, 22 Apr 2014 14:40:32 +0000 Received: from [172.22.42.240] (revolution.hippie.lan [172.22.42.240]) by damnhippie.dyndns.org (8.14.3/8.14.3) with ESMTP id s3MEeSpd008545; Tue, 22 Apr 2014 08:40:28 -0600 (MDT) (envelope-from ian@FreeBSD.org) X-Mail-Handler: Dyn Standard SMTP by Dyn X-Originating-IP: 24.8.230.52 X-Report-Abuse-To: abuse@dyndns.com (see http://www.dyndns.com/services/sendlabs/outbound_abuse.html for abuse reporting information) X-MHO-User: U2FsdGVkX1+6qgGe7rSub64AQVamjXxQ Subject: Re: apu1c led driver From: Ian Lepore To: Larry Baird In-Reply-To: <20140422020109.GA57760@gta.com> References: <20140422020109.GA57760@gta.com> Content-Type: text/plain; charset="us-ascii" Date: Tue, 22 Apr 2014 08:40:28 -0600 Message-ID: <1398177628.1124.406.camel@revolution.hippie.lan> Mime-Version: 1.0 X-Mailer: Evolution 2.32.1 FreeBSD GNOME Team Port Content-Transfer-Encoding: 7bit Cc: freebsd-hackers@FreeBSD.org X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 Apr 2014 14:40:39 -0000 On Mon, 2014-04-21 at 22:01 -0400, Larry Baird wrote: > 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 > #include > #include > #include > #include > #include > #include > > #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); > } > Generally rather than specifying the physical addresses as constants in the device driver, the address space and/or IO port resources are managed by the driver for the bus the device sits on. For something like LEDs and GPIOs that aren't self-identifying devices on a bus and aren't described by ACPI or other system-provided metadata, the 'hints' mechanism gives you a way to provide the resource metadata in /boot/loader.conf. The device.hints(5) manpage has some helpful info. Typically you need to provide an 'at' hint to say which bus the device is on. I'm not sure what's right for your LED/GPIO device; I've only ever used at=isa. For your device, it looks like you also need maddr/msize hints, then bus_alloc_resource_any() with an rid of 0 and a type of MEMORY should get you a bus_space handle for hardware access. -- Ian