Author: mw
Date: Thu Apr 26 19:00:48 2018
New Revision: 333031
URL: https://svnweb.freebsd.org/changeset/base/333031

Log:
  Update mv_gpio driver to new FreeBSD API
  
  This patch implements and exports functions described
  in gpio_if.m file. It also uses new gpiobus_attach_bus function
  instead of adding gpioc and gpiobus as children. It removes
  ulgy reading SoC ID and related if..else, so it depends only on
  data read from FDT.
  
  Submitted by: Patryk Duda <p...@semihalf.com>
  Reviewed by: manu
  Obtained from: Semihalf
  Sponsored by: Stormshield
  Differential Revision: https://reviews.freebsd.org/D14756

Modified:
  head/sys/arm/mv/gpio.c
  head/sys/dts/arm/db78100.dts
  head/sys/dts/arm/db88f5182.dts
  head/sys/dts/arm/db88f5281.dts
  head/sys/dts/arm/db88f6281.dts
  head/sys/dts/arm/dockstar.dts
  head/sys/dts/arm/sheevaplug.dts
  head/sys/dts/bindings-gpio.txt

Modified: head/sys/arm/mv/gpio.c
==============================================================================
--- head/sys/arm/mv/gpio.c      Thu Apr 26 19:00:35 2018        (r333030)
+++ head/sys/arm/mv/gpio.c      Thu Apr 26 19:00:48 2018        (r333031)
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <machine/intr.h>
 
+#include <dev/gpio/gpiobusvar.h>
 #include <dev/fdt/fdt_common.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
@@ -58,8 +59,15 @@ __FBSDID("$FreeBSD$");
 #include <arm/mv/mvvar.h>
 #include <arm/mv/mvreg.h>
 
+#include "gpio_if.h"
+
 #define GPIO_MAX_INTR_COUNT    8
 #define GPIO_PINS_PER_REG      32
+#define GPIO_GENERIC_CAP       (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |             
\
+                               GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL |        
\
+                               GPIO_PIN_TRISTATE | GPIO_PIN_PULLUP |           
\
+                               GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN |            
\
+                               GPIO_PIN_INVOUT)
 
 #define DEBOUNCE_CHECK_MS      1
 #define DEBOUNCE_LO_HI_MS      2
@@ -67,6 +75,7 @@ __FBSDID("$FreeBSD$");
 #define DEBOUNCE_CHECK_TICKS   ((hz / 1000) * DEBOUNCE_CHECK_MS)
 
 struct mv_gpio_softc {
+       device_t                sc_busdev;
        struct resource *       mem_res;
        int                     mem_rid;
        struct resource *       irq_res[GPIO_MAX_INTR_COUNT];
@@ -134,6 +143,19 @@ int mv_gpio_configure(device_t, uint32_t, uint32_t, ui
 void mv_gpio_out(device_t, uint32_t, uint8_t, uint8_t);
 uint8_t mv_gpio_in(device_t, uint32_t);
 
+/*
+ * GPIO interface
+ */
+static device_t mv_gpio_get_bus(device_t);
+static int mv_gpio_pin_max(device_t, int *);
+static int mv_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
+static int mv_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
+static int mv_gpio_pin_getname(device_t, uint32_t, char *);
+static int mv_gpio_pin_setflags(device_t, uint32_t, uint32_t);
+static int mv_gpio_pin_set(device_t, uint32_t, unsigned int);
+static int mv_gpio_pin_get(device_t, uint32_t, unsigned int *);
+static int mv_gpio_pin_toggle(device_t, uint32_t);
+
 #define MV_GPIO_LOCK()         mtx_lock_spin(&sc->mutex)
 #define MV_GPIO_UNLOCK()       mtx_unlock_spin(&sc->mutex)
 #define MV_GPIO_ASSERT_LOCKED()        mtx_assert(&sc->mutex, MA_OWNED)
@@ -141,7 +163,19 @@ uint8_t mv_gpio_in(device_t, uint32_t);
 static device_method_t mv_gpio_methods[] = {
        DEVMETHOD(device_probe,         mv_gpio_probe),
        DEVMETHOD(device_attach,        mv_gpio_attach),
-       { 0, 0 }
+
+       /* GPIO protocol */
+       DEVMETHOD(gpio_get_bus,         mv_gpio_get_bus),
+       DEVMETHOD(gpio_pin_max,         mv_gpio_pin_max),
+       DEVMETHOD(gpio_pin_getname,     mv_gpio_pin_getname),
+       DEVMETHOD(gpio_pin_getflags,    mv_gpio_pin_getflags),
+       DEVMETHOD(gpio_pin_getcaps,     mv_gpio_pin_getcaps),
+       DEVMETHOD(gpio_pin_setflags,    mv_gpio_pin_setflags),
+       DEVMETHOD(gpio_pin_get,         mv_gpio_pin_get),
+       DEVMETHOD(gpio_pin_set,         mv_gpio_pin_set),
+       DEVMETHOD(gpio_pin_toggle,      mv_gpio_pin_toggle),
+
+       DEVMETHOD_END
 };
 
 static driver_t mv_gpio_driver = {
@@ -152,31 +186,23 @@ static driver_t mv_gpio_driver = {
 
 static devclass_t mv_gpio_devclass;
 
-DRIVER_MODULE(gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0);
+DRIVER_MODULE(mv_gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0);
 
-typedef int (*gpios_phandler_t)(device_t, phandle_t, pcell_t *, int);
-
-struct gpio_ctrl_entry {
-       const char              *compat;
-       gpios_phandler_t        handler;
-};
-
 static int mv_handle_gpios_prop(device_t, phandle_t, pcell_t *, int);
-int gpio_get_config_from_dt(void);
 
-struct gpio_ctrl_entry gpio_controllers[] = {
-       { "mrvl,gpio", &mv_handle_gpios_prop },
-       { NULL, NULL }
+struct ofw_compat_data gpio_controllers[] = {
+       { "mrvl,gpio", (uintptr_t)&mv_handle_gpios_prop },
+       { "marvell,orion-gpio", (uintptr_t)&mv_handle_gpios_prop },
+       { NULL, 0 }
 };
 
 static int
 mv_gpio_probe(device_t dev)
 {
-
        if (!ofw_bus_status_okay(dev))
                return (ENXIO);
 
-       if (!ofw_bus_is_compatible(dev, "mrvl,gpio"))
+       if (ofw_bus_search_compatible(dev, gpio_controllers)->ocd_data == 0)
                return (ENXIO);
 
        device_set_desc(dev, "Marvell Integrated GPIO Controller");
@@ -188,7 +214,6 @@ mv_gpio_attach(device_t dev)
 {
        int error, i, size;
        struct mv_gpio_softc *sc;
-       uint32_t dev_id, rev_id;
        pcell_t pincnt = 0;
        pcell_t irq_cells = 0;
        phandle_t iparent;
@@ -197,34 +222,22 @@ mv_gpio_attach(device_t dev)
        if (sc == NULL)
                return (ENXIO);
 
-       /* Get chip id and revision */
-       soc_id(&dev_id, &rev_id);
-
-       if (dev_id == MV_DEV_88F5182 ||
-           dev_id == MV_DEV_88F5281 ||
-           dev_id == MV_DEV_MV78100 ||
-           dev_id == MV_DEV_MV78100_Z0 ) {
-               sc->pin_num = 32;
-               sc->irq_num = 4;
-
-       } else if (dev_id == MV_DEV_88F6281 ||
-           dev_id == MV_DEV_88F6282) {
-               sc->pin_num = 50;
-               sc->irq_num = 7;
-
-       } else {
-               if (OF_getencprop(ofw_bus_get_node(dev), "pin-count", &pincnt,
-                   sizeof(pcell_t)) >= 0 ||
-                   OF_getencprop(ofw_bus_get_node(dev), "ngpios", &pincnt,
-                   sizeof(pcell_t)) >= 0) {
-                       sc->pin_num = pincnt;
+       if (OF_getencprop(ofw_bus_get_node(dev), "pin-count", &pincnt,
+           sizeof(pcell_t)) >= 0 ||
+           OF_getencprop(ofw_bus_get_node(dev), "ngpios", &pincnt,
+           sizeof(pcell_t)) >= 0) {
+               sc->pin_num = MIN(pincnt, MV_GPIO_MAX_NPINS);
+               if (bootverbose)
                        device_printf(dev, "%d pins available\n", sc->pin_num);
-               } else {
-                       device_printf(dev, "ERROR: no pin-count entry 
found!\n");
-                       return (ENXIO);
-               }
+       } else {
+               device_printf(dev, "ERROR: no pin-count or ngpios entry 
found!\n");
+               return (ENXIO);
        }
 
+       /* Assign generic capabilities to every gpio pin */
+       for(i = 0; i < sc->pin_num; i++)
+               sc->gpio_setup[i].gp_caps = GPIO_GENERIC_CAP;
+
        /* Find root interrupt controller */
        iparent = ofw_bus_find_iparent(ofw_bus_get_node(dev));
        if (iparent == 0) {
@@ -315,8 +328,13 @@ mv_gpio_attach(device_t dev)
        /* Clear interrupt status. */
        bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0);
 
-       device_add_child(dev, "gpioc", device_get_unit(dev));
-       device_add_child(dev, "gpiobus", device_get_unit(dev));
+       sc->sc_busdev = gpiobus_attach_bus(dev);
+       if (sc->sc_busdev == NULL) {
+               mtx_destroy(&sc->mutex);
+               bus_release_resource(dev, SYS_RES_IRQ,
+                       sc->irq_rid[i], sc->irq_res[i]);
+               return (ENXIO);
+       }
 
        return (0);
 }
@@ -535,6 +553,16 @@ mv_gpio_configure(device_t dev, uint32_t pin, uint32_t
 
        MV_GPIO_LOCK();
 
+       if ((mask & flags) & GPIO_PIN_INPUT)
+               mv_gpio_out_en(dev, pin, 0);
+       if ((mask & flags) & GPIO_PIN_OUTPUT) {
+               if ((flags & mask) & GPIO_PIN_OPENDRAIN)
+                       mv_gpio_value_set(dev, pin, 0);
+               else
+                       mv_gpio_value_set(dev, pin, 1);
+               mv_gpio_out_en(dev, pin, 1);
+       }
+
        if (mask & MV_GPIO_OUT_BLINK)
                mv_gpio_blink(dev, pin, flags & MV_GPIO_OUT_BLINK);
        if (mask & MV_GPIO_IN_POL_LOW)
@@ -799,7 +827,7 @@ mv_gpio_in(device_t dev, uint32_t pin)
        struct mv_gpio_softc *sc;
        sc = (struct mv_gpio_softc *)device_get_softc(dev);
 
-       MV_GPIO_LOCK();
+       MV_GPIO_ASSERT_LOCKED();
 
        if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) {
                if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW)
@@ -814,7 +842,6 @@ mv_gpio_in(device_t dev, uint32_t pin)
        } else
                state = (mv_gpio_value_get(dev, pin, 0) ? 1 : 0);
 
-
        return (state);
 }
 
@@ -997,6 +1024,8 @@ mv_gpio_value_set(device_t dev, uint32_t pin, uint8_t 
        struct mv_gpio_softc *sc;
        sc = (struct mv_gpio_softc *)device_get_softc(dev);
 
+       MV_GPIO_ASSERT_LOCKED();
+
        if (pin >= sc->pin_num)
                return;
 
@@ -1013,9 +1042,8 @@ mv_handle_gpios_prop(device_t dev, phandle_t ctrl, pce
 {
        pcell_t gpio_cells, pincnt;
        int inc, t, tuples, tuple_size;
-       int dir, flags, pin;
+       int flags, pin;
        u_long gpio_ctrl, size;
-       struct mv_gpio_softc sc;
 
        pincnt = 0;
        if (!OF_hasprop(ctrl, "gpio-controller"))
@@ -1024,7 +1052,7 @@ mv_handle_gpios_prop(device_t dev, phandle_t ctrl, pce
 
        if (OF_getencprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 
0)
                return (ENXIO);
-       if (gpio_cells != 3)
+       if (gpio_cells != 2)
                return (ENXIO);
 
        tuple_size = gpio_cells * sizeof(pcell_t) + sizeof(phandle_t);
@@ -1033,10 +1061,6 @@ mv_handle_gpios_prop(device_t dev, phandle_t ctrl, pce
        if (fdt_regsize(ctrl, &gpio_ctrl, &size))
                return (ENXIO);
 
-       if (OF_getencprop(ctrl, "pin-count", &pincnt, sizeof(pcell_t)) < 0)
-               return (ENXIO);
-       sc.pin_num = pincnt;
-
        /*
         * Skip controller reference, since controller's phandle is given
         * explicitly (in a function argument).
@@ -1046,22 +1070,9 @@ mv_handle_gpios_prop(device_t dev, phandle_t ctrl, pce
 
        for (t = 0; t < tuples; t++) {
                pin = gpios[0];
-               dir = gpios[1];
-               flags = gpios[2];
+               flags = gpios[1];
 
                mv_gpio_configure(dev, pin, flags, ~0);
-
-               if (dir == 1)
-                       /* Input. */
-                       mv_gpio_out_en(dev, pin, 0);
-               else {
-                       /* Output. */
-                       if (flags & MV_GPIO_OUT_OPEN_DRAIN)
-                               mv_gpio_out(dev, pin, 0, 1);
-
-                       if (flags & MV_GPIO_OUT_OPEN_SRC)
-                               mv_gpio_out(dev, pin, 1, 1);
-               }
                gpios += gpio_cells + inc;
        }
 
@@ -1075,12 +1086,13 @@ mv_gpio_init(device_t dev)
 {
        phandle_t child, parent, root, ctrl;
        pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS];
-       struct gpio_ctrl_entry *e;
+       struct ofw_compat_data *e;
        int len, rv;
 
        root = OF_finddevice("/");
        len = 0;
        parent = root;
+       rv = 0;
 
        /* Traverse through entire tree to find nodes with 'gpios' prop */
        for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
@@ -1098,30 +1110,175 @@ mv_gpio_init(device_t dev)
                        /* Get 'gpios' property. */
                        OF_getencprop(child, "gpios", gpios, len);
 
-                       e = (struct gpio_ctrl_entry *)&gpio_controllers;
+                       /*
+                        * First cell of 'gpios' property should
+                        * contain a ref. to a node defining GPIO
+                        * controller.
+                        */
+                       ctrl = OF_node_from_xref(gpios[0]);
 
+                       if(ctrl != ofw_bus_get_node(dev)) {
+                               /* Not this gpio controller */
+                               device_printf(dev, "Not this gpio controller 
ctrl: %x, dev: %x\n",
+                                        ctrl, ofw_bus_get_node(dev));
+                               continue;
+                       }
+
+                       e = gpio_controllers;
+
                        /* Find and call a handler. */
-                       for (; e->compat; e++) {
-                               /*
-                                * First cell of 'gpios' property should
-                                * contain a ref. to a node defining GPIO
-                                * controller.
-                                */
-                               ctrl = OF_node_from_xref(gpios[0]);
+                       for (; e->ocd_str; e++) {
 
-                               if (ofw_bus_node_is_compatible(ctrl, e->compat))
+                               if 
(ofw_bus_node_is_compatible(ctrl,e->ocd_str)) {
                                        /* Call a handler. */
-                                       if ((rv = e->handler(dev, ctrl,
-                                           (pcell_t *)&gpios, len)))
-                                               return (rv);
+                                       rv |= mv_handle_gpios_prop(dev, ctrl,
+                                           (pcell_t *)&gpios, len);
+                               }
                        }
                }
 
-               if (OF_peer(child) == 0) {
+               while (OF_peer(child) == 0 && parent != root) {
                        /* No more siblings. */
                        child = parent;
                        parent = OF_parent(child);
                }
        }
+       return (rv);
+}
+
+static int
+mv_gpio_pin_max(device_t dev, int *maxpin)
+{
+       struct mv_gpio_softc *sc;
+       if (maxpin == NULL)
+               return (EINVAL);
+
+       sc = device_get_softc(dev);
+       *maxpin = sc->pin_num;
+
        return (0);
+}
+
+static int
+mv_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+       struct mv_gpio_softc *sc = device_get_softc(dev);
+       if (caps == NULL)
+               return (EINVAL);
+
+       if (pin >= sc->pin_num)
+               return (EINVAL);
+
+       MV_GPIO_LOCK();
+       *caps = sc->gpio_setup[pin].gp_caps;
+       MV_GPIO_UNLOCK();
+
+       return (0);
+}
+
+static int
+mv_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+       struct mv_gpio_softc *sc = device_get_softc(dev);
+       if (flags == NULL)
+               return (EINVAL);
+
+       if (pin >= sc->pin_num)
+               return (EINVAL);
+
+       MV_GPIO_LOCK();
+       *flags = sc->gpio_setup[pin].gp_flags;
+       MV_GPIO_UNLOCK();
+
+       return (0);
+}
+
+static int
+mv_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+       struct mv_gpio_softc *sc = device_get_softc(dev);
+       if (name == NULL)
+               return (EINVAL);
+
+       if (pin >= sc->pin_num)
+               return (EINVAL);
+
+       MV_GPIO_LOCK();
+       memcpy(name, sc->gpio_setup[pin].gp_name, GPIOMAXNAME);
+       MV_GPIO_UNLOCK();
+
+       return (0);
+}
+
+static int
+mv_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+       int ret;
+       struct mv_gpio_softc *sc = device_get_softc(dev);
+       if (pin >= sc->pin_num)
+               return (EINVAL);
+
+       /* Check for unwanted flags. */
+       if ((flags & sc->gpio_setup[pin].gp_caps) != flags)
+               return (EINVAL);
+
+       ret = mv_gpio_configure(dev, pin, flags, ~0);
+
+       return (ret);
+}
+
+static int
+mv_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+       struct mv_gpio_softc *sc = device_get_softc(dev);
+       if (pin >= sc->pin_num)
+               return (EINVAL);
+
+       MV_GPIO_LOCK();
+       mv_gpio_value_set(dev, pin, value);
+       MV_GPIO_UNLOCK();
+
+       return (0);
+}
+
+static int
+mv_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
+{
+       struct mv_gpio_softc *sc = device_get_softc(dev);
+       if (value == NULL)
+               return (EINVAL);
+
+       if (pin >= sc->pin_num)
+               return (EINVAL);
+
+       MV_GPIO_LOCK();
+       *value = mv_gpio_in(dev, pin);
+       MV_GPIO_UNLOCK();
+
+       return (0);
+}
+
+static int
+mv_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+       struct mv_gpio_softc *sc = device_get_softc(dev);
+       uint32_t value;
+       if (pin >= sc->pin_num)
+               return (EINVAL);
+
+       MV_GPIO_LOCK();
+       value = mv_gpio_in(dev, pin);
+       value = (~value) & 1;
+       mv_gpio_value_set(dev, pin, value);
+       MV_GPIO_UNLOCK();
+
+       return (0);
+}
+
+static device_t
+mv_gpio_get_bus(device_t dev)
+{
+       struct mv_gpio_softc *sc = device_get_softc(dev);
+
+       return (sc->sc_busdev);
 }

Modified: head/sys/dts/arm/db78100.dts
==============================================================================
--- head/sys/dts/arm/db78100.dts        Thu Apr 26 19:00:35 2018        
(r333030)
+++ head/sys/dts/arm/db78100.dts        Thu Apr 26 19:00:48 2018        
(r333031)
@@ -165,7 +165,7 @@
                };
 
                GPIO: gpio@10100 {
-                       #gpio-cells = <3>;
+                       #gpio-cells = <2>;
                        compatible = "mrvl,gpio";
                        reg = <0x10100 0x20>;
                        gpio-controller;

Modified: head/sys/dts/arm/db88f5182.dts
==============================================================================
--- head/sys/dts/arm/db88f5182.dts      Thu Apr 26 19:00:35 2018        
(r333030)
+++ head/sys/dts/arm/db88f5182.dts      Thu Apr 26 19:00:48 2018        
(r333031)
@@ -152,7 +152,7 @@
                };
 
                GPIO: gpio@10100 {
-                       #gpio-cells = <3>;
+                       #gpio-cells = <2>;
                        compatible = "mrvl,gpio";
                        reg = <0x10100 0x20>;
                        gpio-controller;

Modified: head/sys/dts/arm/db88f5281.dts
==============================================================================
--- head/sys/dts/arm/db88f5281.dts      Thu Apr 26 19:00:35 2018        
(r333030)
+++ head/sys/dts/arm/db88f5281.dts      Thu Apr 26 19:00:48 2018        
(r333031)
@@ -152,7 +152,7 @@
                };
 
                GPIO: gpio@10100 {
-                       #gpio-cells = <3>;
+                       #gpio-cells = <2>;
                        compatible = "mrvl,gpio";
                        reg = <0x10100 0x20>;
                        gpio-controller;

Modified: head/sys/dts/arm/db88f6281.dts
==============================================================================
--- head/sys/dts/arm/db88f6281.dts      Thu Apr 26 19:00:35 2018        
(r333030)
+++ head/sys/dts/arm/db88f6281.dts      Thu Apr 26 19:00:48 2018        
(r333031)
@@ -156,7 +156,7 @@
                };
 
                GPIO: gpio@10100 {
-                       #gpio-cells = <3>;
+                       #gpio-cells = <2>;
                        compatible = "mrvl,gpio";
                        reg = <0x10100 0x20>;
                        gpio-controller;

Modified: head/sys/dts/arm/dockstar.dts
==============================================================================
--- head/sys/dts/arm/dockstar.dts       Thu Apr 26 19:00:35 2018        
(r333030)
+++ head/sys/dts/arm/dockstar.dts       Thu Apr 26 19:00:48 2018        
(r333031)
@@ -141,7 +141,7 @@
                };
 
                GPIO: gpio@10100 {
-                       #gpio-cells = <3>;
+                       #gpio-cells = <2>;
                        compatible = "mrvl,gpio";
                        reg = <0x10100 0x20>;
                        gpio-controller;

Modified: head/sys/dts/arm/sheevaplug.dts
==============================================================================
--- head/sys/dts/arm/sheevaplug.dts     Thu Apr 26 19:00:35 2018        
(r333030)
+++ head/sys/dts/arm/sheevaplug.dts     Thu Apr 26 19:00:48 2018        
(r333031)
@@ -153,7 +153,7 @@
                };
 
                GPIO: gpio@10100 {
-                       #gpio-cells = <3>;
+                       #gpio-cells = <2>;
                        compatible = "mrvl,gpio";
                        reg = <0x10100 0x20>;
                        gpio-controller;

Modified: head/sys/dts/bindings-gpio.txt
==============================================================================
--- head/sys/dts/bindings-gpio.txt      Thu Apr 26 19:00:35 2018        
(r333030)
+++ head/sys/dts/bindings-gpio.txt      Thu Apr 26 19:00:48 2018        
(r333031)
@@ -65,37 +65,42 @@ Description:        The gpios property of a device node 
defin
                information like pin number, direction and various flags.
 
 Example:
-               gpios = <&GPIO 0 1 0            /* GPIO[0]:  IN,  NONE */
-                        &GPIO 1 2 0>;          /* GPIO[1]:  OUT, NONE */
+               gpios = <&GPIO 0 1              /* GPIO[0]:  FLAGS */
+                        &GPIO 1 2>;            /* GPIO[1]:  FLAGS */
 
 
-3. "mrvl,gpio" controller GPIO specifier
+3. GPIO controller specifier
 
        <phandle pin dir flags>
 
 
 pin:   0-MAX                           GPIO pin number.
 
-dir:
-       1               IN              Input direction.
-       2               OUT             Output direction.
-
 flags:
-       0x0000----      IN_NONE
-       0x0001----      IN_POL_LOW      Polarity low (active-low).
-       0x0002----      IN_IRQ_EDGE     Interrupt, edge triggered.
-       0x0004----      IN_IRQ_LEVEL    Interrupt, level triggered.
-       
-       0x----0000      OUT_NONE
-       0x----0001      OUT_BLINK       Blink on the pin.
-       0x----0002      OUT_OPEN_DRAIN  Open drain output line.
-       0x----0004      OUT_OPEN_SRC    Open source output line.
+       Available flags are listed in sys/conf.h. Following combination
+       can be supported by the controller. For details please refer
+       to controller's GPIO reference manual.
 
+       GPIO_PIN_INPUT          0x0001  Input direction
+       GPIO_PIN_OUTPUT         0x0002  Output direction
+       GPIO_PIN_OPENDRAIN      0x0004  Open-drain output
+       GPIO_PIN_OPENSOURCE     0x0008  Open-source output
+       GPIO_PIN_PUSHPULL       0x0010  Push-pull output
+       GPIO_PIN_TRISTATE       0x0020  Output disabled
+       GPIO_PIN_PULLUP         0x0040  Internal pull-up enabled
+       GPIO_PIN_PULLDOWN       0x0080  Internal pull-down enabled
+       GPIO_PIN_INVIN          0x0100  Invert input
+       GPIO_PIN_INVOUT         0x0200  Invert output
+       GPIO_PIN_PULSATE        0x0400  Pulsate in hardware
+       GPIO_PIN_IRQ_POL_EDG    0x0800  IRQ active single edge
+       GPIO_PIN_IRQ_POL_DBL    0x1000  IRQ active double edge
+       GPIO_PIN_IRQ_POL_LVL    0x2000  IRQ active level
+       GPIO_PIN_IRQ_DEBOUNCE   0x4000  Debounce on IRQ pin
 
 Example:
-       gpios = <&GPIO 0  1 0x00000000          /* GPIO[0]:   IN */
-                &GPIO 1  2 0x00000000          /* GPIO[1]:   OUT */
-                &GPIO 2  1 0x00020000          /* GPIO[2]:   IN, IRQ (edge) */
-                &GPIO 3  1 0x00040000          /* GPIO[3]:   IN, IRQ (level) */
+       gpios = <&GPIO 0  0x00000001    /* GPIO[0]:   IN */
+                &GPIO 1  0x00000002    /* GPIO[1]:   OUT */
+                &GPIO 2  0x00000801    /* GPIO[2]:   IN, IRQ (edge) */
+                &GPIO 3  0x00004001    /* GPIO[3]:   IN, IRQ (level) */
                 ...
-                &GPIO 10 2 0x00000001>;        /* GPIO[10]:  OUT, blink */
+                &GPIO 10 0x00000401>;  /* GPIO[10]:  OUT, blink */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to