Date: Thu, 13 Feb 2014 17:58:52 +0000 (UTC) From: Luiz Otavio O Souza <loos@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r261843 - in head: share/man/man4 sys/dev/gpio Message-ID: <201402131758.s1DHwqFA084060@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: loos Date: Thu Feb 13 17:58:52 2014 New Revision: 261843 URL: http://svnweb.freebsd.org/changeset/base/261843 Log: Add OFW support to the in tree gpio compatible devices: gpioiic(4) and gpioled(4). Tested on RPi and BBB (using the hardware I2C controller and gpioiic(4) for the I2C tests). It was also verified for regressions on RSPRO (MIPS/ar71xx) used as reference for a non OFW-based system. Update the gpioled(4) and gpioiic(4) man pages with some details and examples about the FDT/OFW support. Some compatibility details pointed out by imp@ will follow in subsequent commits. Approved by: adrian (mentor, implicit) Modified: head/share/man/man4/gpioiic.4 head/share/man/man4/gpioled.4 head/sys/dev/gpio/gpioiic.c head/sys/dev/gpio/gpioled.c Modified: head/share/man/man4/gpioiic.4 ============================================================================== --- head/share/man/man4/gpioiic.4 Thu Feb 13 17:08:29 2014 (r261842) +++ head/share/man/man4/gpioiic.4 Thu Feb 13 17:58:52 2014 (r261843) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 5, 2013 +.Dd February 13, 2014 .Dt GPIOIIC 4 .Os .Sh NAME @@ -65,7 +65,7 @@ This is a bitmask of the pins on the that are to be used for SCLOCK and SDATA from the GPIO IIC bit-banging bus. To configure pin 0 and 7, use the bitmask of -10000001 and convert it to a hexadecimal value of 0x0081. +0b10000001 and convert it to a hexadecimal value of 0x0081. Please note that this mask should only ever have two bits set (any others bits - i.e., pins - will be ignored). .It Va hint.gpioiic.%d.scl @@ -73,13 +73,77 @@ Indicates which bit in the .Va hint.gpioiic.%d.pins should be used as the SCLOCK source. +Optional, defaults to 0. .It Va hint.gpioiic.%d.sda Indicates which bit in the .Va hint.gpioiic.%d.pins should be used as the SDATA source. +Optional, defaults to 1. +.El +.Pp +On a +.Xr FDT 4 +based system, like +.Li ARM , the dts part for a +.Nm gpioiic +device usually looks like: +.Bd -literal +gpio: gpio { + + gpio-controller; + ... + + gpioiic0 { + compatible = "gpioiic"; + /* + * Attach to GPIO pins 21 and 22. Set them + * initially as inputs. + */ + gpios = <&gpio 21 1 0 + &gpio 22 1 0>; + scl = <0>; /* GPIO pin 21 - optional */ + sda = <1>; /* GPIO pin 22 - optional */ + + /* This is an example of a gpioiic child. */ + gpioiic-child0 { + compatible = "lm75"; + i2c-address = <0x4f>; + }; + }; +}; +.Ed +.Pp +Where: +.Bl -tag -width ".Va compatible" +.It Va compatible +Should always be set to "gpioiic". +.It Va gpios +The +.Va gpios +property indicates which GPIO pins should be used for SCLOCK and SDATA +on the GPIO IIC bit-banging bus. +For more details about the +.Va gpios +property, please consult +.Pa /usr/src/sys/boot/fdt/dts/bindings-gpio.txt . +.It Va scl +The +.Va scl +option indicates which bit in the +.Va gpios +should be used as the SCLOCK source. +Optional, defaults to 0. +.It Va sda +The +.Va sda +option indicates which bit in the +.Va gpios +should be used as the SDATA source. +Optional, defaults to 1. .El .Sh SEE ALSO +.Xr fdt 4 , .Xr gpio 4 , .Xr gpioled 4 , .Xr iic 4 , Modified: head/share/man/man4/gpioled.4 ============================================================================== --- head/share/man/man4/gpioled.4 Thu Feb 13 17:08:29 2014 (r261842) +++ head/share/man/man4/gpioled.4 Thu Feb 13 17:58:52 2014 (r261843) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 5, 2013 +.Dd February 13, 2014 .Dt GPIOLED 4 .Os .Sh NAME @@ -68,7 +68,75 @@ Which pin on the GPIO interface to map t Please note that this mask should only ever have one bit set (any others bits - i.e., pins - will be ignored). .El +.Pp +On a +.Xr FDT 4 +based system, like +.Li ARM , the dts part for a +.Nm gpioled +device usually looks like: +.Bd -literal +gpio: gpio { + + gpio-controller; + ... + + led0 { + compatible = "gpioled"; + gpios = <&gpio 16 2 0>; /* GPIO pin 16. */ + name = "ok"; + }; + + led1 { + compatible = "gpioled"; + gpios = <&gpio 17 2 0>; /* GPIO pin 17. */ + name = "user-led1"; + }; +}; +.Ed +.Pp +And optionally, you can choose combine all the leds under a single +.Dq gpio-leds +compatible node: +.Bd -literal +simplebus0 { + + ... + + leds { + compatible = "gpio-leds"; + + led0 { + gpios = <&gpio 16 2 0>; + name = "ok" + }; + + led1 { + gpios = <&gpio 17 2 0>; + name = "user-led1" + }; + }; +}; +.Ed +.Pp +Both methods are equally supported and it is possible to have the leds +defined with any sort of mix between the methods. +The only restriction is that a GPIO pin cannot be mapped by two different +(gpio)leds. +.Pp +For more details about the +.Va gpios +property, please consult +.Pa /usr/src/sys/boot/fdt/dts/bindings-gpio.txt . +.Pp +The property +.Va name +is the arbitrary name of device in +.Pa /dev/led/ +to create for +.Xr led 4 . .Sh SEE ALSO +.Xr fdt 4 , .Xr gpio 4 , .Xr led 4 , .Xr gpioiic 4 Modified: head/sys/dev/gpio/gpioiic.c ============================================================================== --- head/sys/dev/gpio/gpioiic.c Thu Feb 13 17:08:29 2014 (r261842) +++ head/sys/dev/gpio/gpioiic.c Thu Feb 13 17:58:52 2014 (r261843) @@ -28,6 +28,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> @@ -38,6 +40,12 @@ __FBSDID("$FreeBSD$"); #include <sys/gpio.h> #include "gpiobus_if.h" +#ifdef FDT +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/fdt/fdt_common.h> +#endif + #include <dev/iicbus/iiconf.h> #include <dev/iicbus/iicbus.h> @@ -71,6 +79,10 @@ static int gpioiic_probe(device_t dev) { +#ifdef FDT + if (!ofw_bus_is_compatible(dev, "gpioiic")) + return (ENXIO); +#endif device_set_desc(dev, "GPIO I2C bit-banging driver"); return (0); @@ -81,6 +93,10 @@ gpioiic_attach(device_t dev) { struct gpioiic_softc *sc = device_get_softc(dev); device_t bitbang; +#ifdef FDT + phandle_t node; + pcell_t pin; +#endif sc->sc_dev = dev; sc->sc_busdev = device_get_parent(dev); @@ -91,6 +107,15 @@ gpioiic_attach(device_t dev) device_get_unit(dev), "sda", &sc->sda_pin)) sc->sda_pin = SDA_PIN_DEFAULT; +#ifdef FDT + if ((node = ofw_bus_get_node(dev)) == -1) + return (ENXIO); + if (OF_getencprop(node, "scl", &pin, sizeof(pin)) > 0) + sc->scl_pin = (int)pin; + if (OF_getencprop(node, "sda", &pin, sizeof(pin)) > 0) + sc->sda_pin = (int)pin; +#endif + /* add generic bit-banging code */ bitbang = device_add_child(dev, "iicbb", -1); device_probe_and_attach(bitbang); @@ -209,6 +234,16 @@ gpioiic_reset(device_t dev, u_char speed return (IIC_ENOADDR); } +#ifdef FDT +static phandle_t +gpioiic_get_node(device_t bus, device_t dev) +{ + + /* We only have one child, the iicbb, which needs our own node. */ + return (ofw_bus_get_node(bus)); +} +#endif + static devclass_t gpioiic_devclass; static device_method_t gpioiic_methods[] = { @@ -225,6 +260,11 @@ static device_method_t gpioiic_methods[] DEVMETHOD(iicbb_getscl, gpioiic_getscl), DEVMETHOD(iicbb_reset, gpioiic_reset), +#ifdef FDT + /* OFW bus interface */ + DEVMETHOD(ofw_bus_get_node, gpioiic_get_node), +#endif + { 0, 0 } }; Modified: head/sys/dev/gpio/gpioled.c ============================================================================== --- head/sys/dev/gpio/gpioled.c Thu Feb 13 17:08:29 2014 (r261842) +++ head/sys/dev/gpio/gpioled.c Thu Feb 13 17:58:52 2014 (r261843) @@ -27,6 +27,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/bio.h> @@ -39,6 +41,12 @@ __FBSDID("$FreeBSD$"); #include <sys/module.h> #include <sys/mutex.h> +#ifdef FDT +#include <dev/fdt/fdt_common.h> +#include <dev/gpio/gpiobusvar.h> +#include <dev/ofw/ofw_bus.h> +#endif + #include <dev/led/led.h> #include <sys/gpio.h> #include "gpiobus_if.h" @@ -84,10 +92,65 @@ gpioled_control(void *priv, int onoff) GPIOLED_UNLOCK(sc); } +#ifdef FDT +static void +gpioled_identify(driver_t *driver, device_t bus) +{ + phandle_t child, leds, root; + + root = OF_finddevice("/"); + if (root == 0) + return; + leds = fdt_find_compatible(root, "gpio-leds", 1); + if (leds == 0) + return; + + /* Traverse the 'gpio-leds' node and add its children. */ + for (child = OF_child(leds); child != 0; child = OF_peer(child)) + if (ofw_gpiobus_add_fdt_child(bus, child) == NULL) + continue; +} +#endif + static int gpioled_probe(device_t dev) { +#ifdef FDT + int match; + phandle_t node; + char *compat; + + /* + * We can match against our own node compatible string and also against + * our parent node compatible string. The first is normally used to + * describe leds on a gpiobus and the later when there is a common node + * compatible with 'gpio-leds' which is used to concentrate all the + * leds nodes on the dts. + */ + match = 0; + if (ofw_bus_is_compatible(dev, "gpioled")) + match = 1; + + if (match == 0) { + if ((node = ofw_bus_get_node(dev)) == -1) + return (ENXIO); + if ((node = OF_parent(node)) == -1) + return (ENXIO); + if (OF_getprop_alloc(node, "compatible", 1, + (void **)&compat) == -1) + return (ENXIO); + + if (strcasecmp(compat, "gpio-leds") == 0) + match = 1; + + free(compat, M_OFWPROP); + } + + if (match == 0) + return (ENXIO); +#endif device_set_desc(dev, "GPIO led"); + return (0); } @@ -95,18 +158,35 @@ static int gpioled_attach(device_t dev) { struct gpioled_softc *sc; +#ifdef FDT + phandle_t node; + char *name; +#else const char *name; +#endif sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_busdev = device_get_parent(dev); GPIOLED_LOCK_INIT(sc); +#ifdef FDT + name = NULL; + if ((node = ofw_bus_get_node(dev)) == -1) + return (ENXIO); + if (OF_getprop_alloc(node, "label", 1, (void **)&name) == -1) + OF_getprop_alloc(node, "name", 1, (void **)&name); +#else if (resource_string_value(device_get_name(dev), device_get_unit(dev), "name", &name)) name = NULL; +#endif sc->sc_leddev = led_create(gpioled_control, sc, name ? name : device_get_nameunit(dev)); +#ifdef FDT + if (name != NULL) + free(name, M_OFWPROP); +#endif return (0); } @@ -129,6 +209,9 @@ static devclass_t gpioled_devclass; static device_method_t gpioled_methods[] = { /* Device interface */ +#ifdef FDT + DEVMETHOD(device_identify, gpioled_identify), +#endif DEVMETHOD(device_probe, gpioled_probe), DEVMETHOD(device_attach, gpioled_attach), DEVMETHOD(device_detach, gpioled_detach),
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201402131758.s1DHwqFA084060>