From owner-freebsd-arch@FreeBSD.ORG Tue Dec 4 19:19:16 2012 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id E69B6F5F for ; Tue, 4 Dec 2012 19:19:15 +0000 (UTC) (envelope-from loos.br@gmail.com) Received: from mail-vc0-f182.google.com (mail-vc0-f182.google.com [209.85.220.182]) by mx1.freebsd.org (Postfix) with ESMTP id 88E4D8FC0C for ; Tue, 4 Dec 2012 19:19:15 +0000 (UTC) Received: by mail-vc0-f182.google.com with SMTP id fo14so4480366vcb.13 for ; Tue, 04 Dec 2012 11:19:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:content-type:subject:date:message-id:to:mime-version:x-mailer; bh=kOtafFHLyz8w14wZh73n4ktz7ZaaRRMvhjKQQxZrYDE=; b=sw8f9sXL97icQWxVt9eydGchh8YvXw0O/piq8f527RGnL7tHWBTlH+X2LsN7eR5NJN fADQSbk7MG9OSAUrgWrT7fKCblYidvRiiBq4F9+ngB8BmSE+Wy8cXxk4a1Nrx7YVl1cs viemytan24iD0egUNfrl5BQRD8JwJpXMh57EzkRimbObTh4uLDo+ML7w5+XfVOZae2L4 1Gj7Y9ezxFFbm00UIejwD42Arz23WE9l3tT5NA3JvGeI8pIR1jLEkUiN2MRmOOGAe2/K s/Yq5xcIM7MXrufWQSKWTLUy3zRv6Ipr/wmejac9TsdooXFTzgWGH+vq6/Zd2leCipsm VIeQ== Received: by 10.52.23.6 with SMTP id i6mr10851362vdf.100.1354648754498; Tue, 04 Dec 2012 11:19:14 -0800 (PST) Received: from [10.1.10.65] ([187.120.137.162]) by mx.google.com with ESMTPS id y7sm804335vdt.14.2012.12.04.11.19.12 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 04 Dec 2012 11:19:13 -0800 (PST) From: Luiz Otavio O Souza Content-Type: multipart/mixed; boundary=Apple-Mail-16-531908476 Subject: FDT Support for GPIO (gpiobus and friends) Date: Tue, 4 Dec 2012 17:19:06 -0200 Message-Id: To: freebsd-arch@freebsd.org Mime-Version: 1.0 (Apple Message framework v1084) X-Mailer: Apple Mail (2.1084) X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 Dec 2012 19:19:16 -0000 --Apple-Mail-16-531908476 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Hi, I've been playing with GPIO on RPi and found the missing support of FDT = on gpiobus very annoying. The following patch (gpio-fdt.diff) adds FDT support to GPIO (gpiobus, = gpioc, gpioled). The bcm2835_gpio.c.fdt.diff will add (a better) support of FDT on RPi = GPIO controller and the bcm2835.dts.diff has my changes on the RPi dts = for adding support of gpioled on 'ok' led (pin 16). Comments ? Thanks, Luiz --Apple-Mail-16-531908476 Content-Disposition: attachment; filename=gpio-fdt.diff Content-Type: application/octet-stream; name="gpio-fdt.diff" Content-Transfer-Encoding: 7bit Index: dev/gpio/gpiobus.c =================================================================== --- dev/gpio/gpiobus.c (revision 243614) +++ dev/gpio/gpiobus.c (working copy) @@ -46,6 +46,12 @@ #include "gpio_if.h" #include "gpiobus_if.h" +#ifdef FDT +#include +#include +#include +#endif + static void gpiobus_print_pins(struct gpiobus_ivar *); static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int); static int gpiobus_probe(device_t); @@ -169,9 +175,64 @@ return (0); } +#ifdef FDT static int +gpiobus_fdt_parse_pins(struct gpiobus_softc *sc, struct gpiobus_ivar *devi, + device_t child, phandle_t pchild) +{ + int i, len; + pcell_t *pins; + + if ((len = OF_getproplen(pchild, "pins")) == -1) + return (-1); + + pins = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); + if (pins == NULL) + return (-1); + + if (OF_getprop(pchild, "pins", pins, len) == -1) { + free(pins, M_DEVBUF); + return (-1); + } + + devi->npins = len / sizeof(pcell_t); + devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF, + M_NOWAIT | M_ZERO); + if (devi->pins == NULL) { + free(pins, M_DEVBUF); + return (-1); + } + + for (i = 0; i < devi->npins; i++) { + devi->pins[i] = fdt32_to_cpu(pins[i]); + + /* + * Mark pin as mapped and give warning if it's already mapped + */ + if (sc->sc_pins_mapped[devi->pins[i]]) { + device_printf(child, + "warning: pin %d is already mapped\n", + devi->pins[i]); + free(pins, M_DEVBUF); + return (-1); + } + sc->sc_pins_mapped[devi->pins[i]] = 1; + } + + free(pins, M_DEVBUF); + return (0); +} +#endif + +static int gpiobus_probe(device_t dev) { + +#ifdef FDT + if (!ofw_bus_is_compatible(dev, "gpiobus")) + return (ENXIO); +#endif + device_set_desc(dev, "GPIO bus"); return (0); } @@ -179,6 +240,11 @@ static int gpiobus_attach(device_t dev) { +#ifdef FDT + device_t dev_child; + phandle_t dt_node, dt_child; + struct gpiobus_ivar *devi; +#endif struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); int res; @@ -208,6 +274,53 @@ * Get parent's pins and mark them as unmapped */ bus_enumerate_hinted_children(dev); + +#ifdef FDT + /* + * Walk gpiobus and add direct subordinates as our children. + */ + dt_node = ofw_bus_get_node(dev); + for (dt_child = OF_child(dt_node); dt_child != 0; + dt_child = OF_peer(dt_child)) { + + /* Check and process 'status' property. */ + if (!(fdt_is_enabled(dt_child))) + continue; + + /* The GPIO pins are mandatory. */ + if (!OF_hasprop(dt_child, "pins")) + continue; + + devi = malloc(sizeof(*devi), M_DEVBUF, M_WAITOK | M_ZERO); + + if (ofw_bus_gen_setup_devinfo(&devi->ofw, dt_child) != 0) { + free(devi, M_DEVBUF); + device_printf(dev, "could not set up devinfo\n"); + continue; + } + + /* Add newbus device for this FDT node */ + dev_child = device_add_child(dev, NULL, -1); + if (dev_child == NULL) { + device_printf(dev, "could not add child: %s\n", + devi->ofw.obd_name); + /* XXX should unmap */ + ofw_bus_gen_destroy_devinfo(&devi->ofw); + free(devi, M_DEVBUF); + continue; + } + device_set_ivars(dev_child, devi); + + if (gpiobus_fdt_parse_pins(sc, + devi, dev_child, dt_child) != 0) { + device_delete_child(dev, dev_child); + ofw_bus_gen_destroy_devinfo(&devi->ofw); + free(devi, M_DEVBUF); + continue; + } + } +#endif + return (bus_generic_attach(dev)); } @@ -445,6 +558,17 @@ return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]); } +#ifdef FDT +static const struct ofw_bus_devinfo * +gpiobus_get_devinfo(device_t bus, device_t child) +{ + struct gpiobus_ivar *devi; + + devi = device_get_ivars(child); + return (&devi->ofw); +} +#endif + static device_method_t gpiobus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, gpiobus_probe), @@ -473,6 +597,16 @@ DEVMETHOD(gpiobus_pin_set, gpiobus_pin_set), DEVMETHOD(gpiobus_pin_toggle, gpiobus_pin_toggle), +#ifdef FDT + /* OFW bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, gpiobus_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), +#endif + DEVMETHOD_END }; Index: dev/gpio/gpiobusvar.h =================================================================== --- dev/gpio/gpiobusvar.h (revision 243614) +++ dev/gpio/gpiobusvar.h (working copy) @@ -34,6 +34,12 @@ #include #include +#include "opt_platform.h" + +#ifdef FDT +#include +#endif + #define GPIOBUS_IVAR(d) (struct gpiobus_ivar *) device_get_ivars(d) #define GPIOBUS_SOFTC(d) (struct gpiobus_softc *) device_get_softc(d) @@ -50,6 +56,9 @@ struct gpiobus_ivar { +#ifdef FDT + struct ofw_bus_devinfo ofw; /* FDT device info */ +#endif uint32_t npins; /* pins total */ uint32_t *pins; /* pins map */ }; Index: dev/gpio/gpioc.c =================================================================== --- dev/gpio/gpioc.c (revision 243614) +++ dev/gpio/gpioc.c (working copy) @@ -44,6 +44,13 @@ #include #include "gpio_if.h" +#include "opt_platform.h" + +#ifdef FDT +#include +#include +#endif + #undef GPIOC_DEBUG #ifdef GPIOC_DEBUG #define dprintf printf @@ -73,6 +80,11 @@ static int gpioc_probe(device_t dev) { + +#ifdef FDT + if (!ofw_bus_is_compatible(dev, "gpio-controller")) + return (ENXIO); +#endif device_set_desc(dev, "GPIO controller"); return (0); } Index: dev/gpio/gpioled.c =================================================================== --- dev/gpio/gpioled.c (revision 243614) +++ dev/gpio/gpioled.c (working copy) @@ -43,11 +43,20 @@ #include #include "gpiobus_if.h" +#include "opt_platform.h" + +#ifdef FDT +#include +#include +#endif + /* * Only one pin for led */ #define GPIOLED_PIN 0 +#define GPIOLED_MAXBUF 32 + #define GPIOLED_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define GPIOLED_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define GPIOLED_LOCK_INIT(_sc) \ @@ -85,6 +94,11 @@ static int gpioled_probe(device_t dev) { + +#ifdef FDT + if (!ofw_bus_is_compatible(dev, "gpioled")) + return (ENXIO); +#endif device_set_desc(dev, "GPIO led"); return (0); } @@ -92,16 +106,27 @@ static int gpioled_attach(device_t dev) { +#ifdef FDT + phandle_t node; +#endif struct gpioled_softc *sc; - const char *name; + char *name; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_busdev = device_get_parent(dev); GPIOLED_LOCK_INIT(sc); + +#ifdef FDT + node = ofw_bus_get_node(dev); + name = malloc(GPIOLED_MAXBUF + 1, M_DEVBUF, M_NOWAIT | M_ZERO); + if (OF_getprop(node, "label", name, GPIOLED_MAXBUF) == -1) + OF_getprop(node, "name", name, GPIOLED_MAXBUF); +#else if (resource_string_value(device_get_name(dev), device_get_unit(dev), "name", &name)) name = NULL; +#endif GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, GPIOLED_PIN, GPIO_PIN_OUTPUT); @@ -109,6 +134,9 @@ sc->sc_leddev = led_create(gpioled_control, sc, name ? name : device_get_nameunit(dev)); +#ifdef FDT + free(name, M_DEVBUF); +#endif return (0); } --Apple-Mail-16-531908476 Content-Disposition: attachment; filename=bcm2835_gpio.c.fdt.diff Content-Type: application/octet-stream; name="bcm2835_gpio.c.fdt.diff" Content-Transfer-Encoding: 7bit --- arm/broadcom/bcm2835/bcm2835_gpio.c.orig 2012-12-03 15:39:23.762869715 -0200 +++ arm/broadcom/bcm2835/bcm2835_gpio.c 2012-12-04 16:22:40.133869246 -0200 @@ -689,9 +689,11 @@ bcm_gpio_attach(device_t dev) { struct bcm_gpio_softc *sc = device_get_softc(dev); + struct ofw_bus_devinfo *di_ofw; + device_t dev_child; uint32_t func; int i, j, rid; - phandle_t gpio; + phandle_t child, gpio; sc->sc_dev = dev; @@ -747,8 +749,39 @@ bcm_gpio_sysctl_init(sc); - device_add_child(dev, "gpioc", device_get_unit(dev)); - device_add_child(dev, "gpiobus", device_get_unit(dev)); + /* + * Walkthrough our node and add direct subordinates as our children. + */ + for (child = OF_child(gpio); child != 0; child = OF_peer(child)) { + + /* Check and process 'status' property. */ + if (!(fdt_is_enabled(child))) + continue; + + if (!OF_hasprop(child, "compatible")) + continue; + + di_ofw = malloc(sizeof(*di_ofw), M_DEVBUF, M_WAITOK | M_ZERO); + + if (ofw_bus_gen_setup_devinfo(di_ofw, child) != 0) { + free(di_ofw, M_DEVBUF); + device_printf(dev, "could not set up devinfo\n"); + continue; + } + + /* Add newbus device for this FDT node */ + dev_child = device_add_child(dev, NULL, -1); + if (dev_child == NULL) { + device_printf(dev, "could not add child: %s\n", + di_ofw->obd_name); + /* XXX should unmap */ + ofw_bus_gen_destroy_devinfo(di_ofw); + free(di_ofw, M_DEVBUF); + continue; + } + device_set_ivars(dev_child, di_ofw); + } + return (bus_generic_attach(dev)); fail: @@ -766,6 +799,13 @@ return (EBUSY); } +static const struct ofw_bus_devinfo * +bcm_gpio_get_devinfo(device_t bus, device_t child) +{ + + return (device_get_ivars(child)); +} + static device_method_t bcm_gpio_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bcm_gpio_probe), @@ -782,6 +822,14 @@ DEVMETHOD(gpio_pin_set, bcm_gpio_pin_set), DEVMETHOD(gpio_pin_toggle, bcm_gpio_pin_toggle), + /* OFW bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, bcm_gpio_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + DEVMETHOD_END }; --Apple-Mail-16-531908476 Content-Disposition: attachment; filename=bcm2835.dts.diff Content-Type: application/octet-stream; name="bcm2835.dts.diff" Content-Transfer-Encoding: 7bit Index: boot/fdt/dts/bcm2835-rpi-b.dts =================================================================== --- boot/fdt/dts/bcm2835-rpi-b.dts (revision 243614) +++ boot/fdt/dts/bcm2835-rpi-b.dts (working copy) @@ -173,6 +173,21 @@ */ broadcom,read-only = <46>, <47>, <48>, <49>, <50>, <51>, <52>, <53>; + gpioc { + compatible = "gpio-controller"; + }; + + gpiobus { + compatible = "gpiobus"; + + /* Ok led */ + led { + compatible = "gpioled"; + label = "ok"; + pins = <16>; + }; + }; + /* BSC0 */ pins_bsc0_a: bsc0_a { broadcom,pins = <0>, <1>; --Apple-Mail-16-531908476--