The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/nvidia/as3722_gpio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/gpio.h>
   34 #include <sys/kernel.h>
   35 #include <sys/malloc.h>
   36 #include <sys/sx.h>
   37 
   38 #include <machine/bus.h>
   39 
   40 #include <dev/fdt/fdt_common.h>
   41 #include <dev/gpio/gpiobusvar.h>
   42 
   43 #include "as3722.h"
   44 
   45 MALLOC_DEFINE(M_AS3722_GPIO, "AS3722 gpio", "AS3722 GPIO");
   46 
   47 /* AS3722_GPIOx_CONTROL  MODE and IOSF definition. */
   48 #define AS3722_IOSF_GPIO                                0x00
   49 #define AS3722_IOSF_INTERRUPT_OUT                       0x01
   50 #define AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT        0x02
   51 #define AS3722_IOSF_GPIO_IN_INTERRUPT                   0x03
   52 #define AS3722_IOSF_PWM_IN                              0x04
   53 #define AS3722_IOSF_VOLTAGE_IN_STANDBY                  0x05
   54 #define AS3722_IOSF_OC_PG_SD0                           0x06
   55 #define AS3722_IOSF_POWERGOOD_OUT                       0x07
   56 #define AS3722_IOSF_CLK32K_OUT                          0x08
   57 #define AS3722_IOSF_WATCHDOG_IN                         0x09
   58 #define AS3722_IOSF_SOFT_RESET_IN                       0x0b
   59 #define AS3722_IOSF_PWM_OUT                             0x0c
   60 #define AS3722_IOSF_VSUP_VBAT_LOW_DEBOUNCE_OUT          0x0d
   61 #define AS3722_IOSF_OC_PG_SD6                           0x0e
   62 
   63 #define AS3722_MODE_INPUT                               0
   64 #define AS3722_MODE_PUSH_PULL                           1
   65 #define AS3722_MODE_OPEN_DRAIN                          2
   66 #define AS3722_MODE_TRISTATE                            3
   67 #define AS3722_MODE_INPUT_PULL_UP_LV                    4
   68 #define AS3722_MODE_INPUT_PULL_DOWN                     5
   69 #define AS3722_MODE_OPEN_DRAIN_LV                       6
   70 #define AS3722_MODE_PUSH_PULL_LV                        7
   71 
   72 #define NGPIO           8
   73 
   74 #define GPIO_LOCK(_sc)  sx_slock(&(_sc)->gpio_lock)
   75 #define GPIO_UNLOCK(_sc)        sx_unlock(&(_sc)->gpio_lock)
   76 #define GPIO_ASSERT(_sc)        sx_assert(&(_sc)->gpio_lock, SA_LOCKED)
   77 
   78 #define AS3722_CFG_BIAS_DISABLE         0x0001
   79 #define AS3722_CFG_BIAS_PULL_UP         0x0002
   80 #define AS3722_CFG_BIAS_PULL_DOWN       0x0004
   81 #define AS3722_CFG_BIAS_HIGH_IMPEDANCE  0x0008
   82 #define AS3722_CFG_OPEN_DRAIN           0x0010
   83 
   84 static const struct {
   85         const char      *name;
   86         int             config;         /* AS3722_CFG_  */
   87 } as3722_cfg_names[] = {
   88         {"bias-disable",        AS3722_CFG_BIAS_DISABLE},
   89         {"bias-pull-up",        AS3722_CFG_BIAS_PULL_UP},
   90         {"bias-pull-down",      AS3722_CFG_BIAS_PULL_DOWN},
   91         {"bias-high-impedance", AS3722_CFG_BIAS_HIGH_IMPEDANCE},
   92         {"drive-open-drain",    AS3722_CFG_OPEN_DRAIN},
   93 };
   94 
   95 static struct {
   96         const char *name;
   97         int fnc_val;
   98 } as3722_fnc_table[] = {
   99         {"gpio",                        AS3722_IOSF_GPIO},
  100         {"interrupt-out",               AS3722_IOSF_INTERRUPT_OUT},
  101         {"vsup-vbat-low-undebounce-out", AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT},
  102         {"gpio-in-interrupt",           AS3722_IOSF_GPIO_IN_INTERRUPT},
  103         {"pwm-in",                      AS3722_IOSF_PWM_IN},
  104         {"voltage-in-standby",          AS3722_IOSF_VOLTAGE_IN_STANDBY},
  105         {"oc-pg-sd0",                   AS3722_IOSF_OC_PG_SD0},
  106         {"powergood-out",               AS3722_IOSF_POWERGOOD_OUT},
  107         {"clk32k-out",                  AS3722_IOSF_CLK32K_OUT},
  108         {"watchdog-in",                 AS3722_IOSF_WATCHDOG_IN},
  109         {"soft-reset-in",               AS3722_IOSF_SOFT_RESET_IN},
  110         {"pwm-out",                     AS3722_IOSF_PWM_OUT},
  111         {"vsup-vbat-low-debounce-out",  AS3722_IOSF_VSUP_VBAT_LOW_DEBOUNCE_OUT},
  112         {"oc-pg-sd6",                   AS3722_IOSF_OC_PG_SD6},
  113 };
  114 
  115 struct as3722_pincfg {
  116         char    *function;
  117         int     flags;
  118 };
  119 
  120 struct as3722_gpio_pin {
  121         int     pin_caps;
  122         uint8_t pin_ctrl_reg;
  123         char    pin_name[GPIOMAXNAME];
  124         int     pin_cfg_flags;
  125 };
  126 
  127 /* --------------------------------------------------------------------------
  128  *
  129  *  Pinmux functions.
  130  */
  131 static int
  132 as3722_pinmux_get_function(struct as3722_softc *sc, char *name)
  133 {
  134         int i;
  135 
  136         for (i = 0; i < nitems(as3722_fnc_table); i++) {
  137                 if (strcmp(as3722_fnc_table[i].name, name) == 0)
  138                          return (as3722_fnc_table[i].fnc_val);
  139         }
  140         return (-1);
  141 }
  142 
  143 static int
  144 as3722_pinmux_config_node(struct as3722_softc *sc, char *pin_name,
  145     struct as3722_pincfg *cfg)
  146 {
  147         uint8_t ctrl;
  148         int rv, fnc, pin;
  149 
  150         for (pin = 0; pin < sc->gpio_npins; pin++) {
  151                 if (strcmp(sc->gpio_pins[pin]->pin_name, pin_name) == 0)
  152                          break;
  153         }
  154         if (pin >= sc->gpio_npins) {
  155                 device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
  156                 return (ENXIO);
  157         }
  158 
  159         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
  160         sc->gpio_pins[pin]->pin_cfg_flags = cfg->flags;
  161         if (cfg->function != NULL) {
  162                 fnc = as3722_pinmux_get_function(sc, cfg->function);
  163                 if (fnc == -1) {
  164                         device_printf(sc->dev,
  165                             "Unknown function %s for pin %s\n", cfg->function,
  166                             sc->gpio_pins[pin]->pin_name);
  167                         return (ENXIO);
  168                 }
  169                 switch (fnc) {
  170                 case AS3722_IOSF_INTERRUPT_OUT:
  171                 case AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT:
  172                 case AS3722_IOSF_OC_PG_SD0:
  173                 case AS3722_IOSF_POWERGOOD_OUT:
  174                 case AS3722_IOSF_CLK32K_OUT:
  175                 case AS3722_IOSF_PWM_OUT:
  176                 case AS3722_IOSF_OC_PG_SD6:
  177                         ctrl &= ~(AS3722_GPIO_MODE_MASK <<
  178                             AS3722_GPIO_MODE_SHIFT);
  179                         ctrl |= AS3722_MODE_PUSH_PULL << AS3722_GPIO_MODE_SHIFT;
  180                         /* XXX Handle flags (OC + pullup) */
  181                         break;
  182                 case AS3722_IOSF_GPIO_IN_INTERRUPT:
  183                 case AS3722_IOSF_PWM_IN:
  184                 case AS3722_IOSF_VOLTAGE_IN_STANDBY:
  185                 case AS3722_IOSF_WATCHDOG_IN:
  186                 case AS3722_IOSF_SOFT_RESET_IN:
  187                         ctrl &= ~(AS3722_GPIO_MODE_MASK <<
  188                             AS3722_GPIO_MODE_SHIFT);
  189                         ctrl |= AS3722_MODE_INPUT << AS3722_GPIO_MODE_SHIFT;
  190                         /* XXX Handle flags (pulldown + pullup) */
  191 
  192                 default:
  193                         break;
  194                 }
  195                 ctrl &= ~(AS3722_GPIO_IOSF_MASK << AS3722_GPIO_IOSF_SHIFT);
  196                 ctrl |= fnc << AS3722_GPIO_IOSF_SHIFT;
  197         }
  198         rv = 0;
  199         if (ctrl != sc->gpio_pins[pin]->pin_ctrl_reg) {
  200                 rv = WR1(sc, AS3722_GPIO0_CONTROL + pin, ctrl);
  201                 sc->gpio_pins[pin]->pin_ctrl_reg = ctrl;
  202         }
  203         return (rv);
  204 }
  205 
  206 static int
  207 as3722_pinmux_read_node(struct as3722_softc *sc, phandle_t node,
  208      struct as3722_pincfg *cfg, char **pins, int *lpins)
  209 {
  210         int rv, i;
  211 
  212         *lpins = OF_getprop_alloc(node, "pins", (void **)pins);
  213         if (*lpins <= 0)
  214                 return (ENOENT);
  215 
  216         /* Read function (mux) settings. */
  217         rv = OF_getprop_alloc(node, "function", (void **)&cfg->function);
  218         if (rv <= 0)
  219                 cfg->function = NULL;
  220 
  221         /* Read boolean properties. */
  222         for (i = 0; i < nitems(as3722_cfg_names); i++) {
  223                 if (OF_hasprop(node, as3722_cfg_names[i].name))
  224                         cfg->flags |= as3722_cfg_names[i].config;
  225         }
  226         return (0);
  227 }
  228 
  229 static int
  230 as3722_pinmux_process_node(struct as3722_softc *sc, phandle_t node)
  231 {
  232         struct as3722_pincfg cfg;
  233         char *pins, *pname;
  234         int i, len, lpins, rv;
  235 
  236         rv = as3722_pinmux_read_node(sc, node, &cfg, &pins, &lpins);
  237         if (rv != 0)
  238                 return (rv);
  239 
  240         len = 0;
  241         pname = pins;
  242         do {
  243                 i = strlen(pname) + 1;
  244                 rv = as3722_pinmux_config_node(sc, pname, &cfg);
  245                 if (rv != 0) {
  246                         device_printf(sc->dev,
  247                             "Cannot configure pin: %s: %d\n", pname, rv);
  248                 }
  249                 len += i;
  250                 pname += i;
  251         } while (len < lpins);
  252 
  253         if (pins != NULL)
  254                 OF_prop_free(pins);
  255         if (cfg.function != NULL)
  256                 OF_prop_free(cfg.function);
  257 
  258         return (rv);
  259 }
  260 
  261 int as3722_pinmux_configure(device_t dev, phandle_t cfgxref)
  262 {
  263         struct as3722_softc *sc;
  264         phandle_t node, cfgnode;
  265         int rv;
  266 
  267         sc = device_get_softc(dev);
  268         cfgnode = OF_node_from_xref(cfgxref);
  269 
  270         for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
  271                 if (!ofw_bus_node_status_okay(node))
  272                         continue;
  273                 rv = as3722_pinmux_process_node(sc, node);
  274                 if (rv != 0)
  275                         device_printf(dev, "Failed to process pinmux");
  276         }
  277         return (0);
  278 }
  279 
  280 /* --------------------------------------------------------------------------
  281  *
  282  *  GPIO
  283  */
  284 device_t
  285 as3722_gpio_get_bus(device_t dev)
  286 {
  287         struct as3722_softc *sc;
  288 
  289         sc = device_get_softc(dev);
  290         return (sc->gpio_busdev);
  291 }
  292 
  293 int
  294 as3722_gpio_pin_max(device_t dev, int *maxpin)
  295 {
  296 
  297         *maxpin = NGPIO - 1;
  298         return (0);
  299 }
  300 
  301 int
  302 as3722_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  303 {
  304         struct as3722_softc *sc;
  305 
  306         sc = device_get_softc(dev);
  307         if (pin >= sc->gpio_npins)
  308                 return (EINVAL);
  309         GPIO_LOCK(sc);
  310         *caps = sc->gpio_pins[pin]->pin_caps;
  311         GPIO_UNLOCK(sc);
  312         return (0);
  313 }
  314 
  315 int
  316 as3722_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  317 {
  318         struct as3722_softc *sc;
  319 
  320         sc = device_get_softc(dev);
  321         if (pin >= sc->gpio_npins)
  322                 return (EINVAL);
  323         GPIO_LOCK(sc);
  324         memcpy(name, sc->gpio_pins[pin]->pin_name, GPIOMAXNAME);
  325         GPIO_UNLOCK(sc);
  326         return (0);
  327 }
  328 
  329 int
  330 as3722_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *out_flags)
  331 {
  332         struct as3722_softc *sc;
  333         uint8_t tmp, mode, iosf;
  334         uint32_t flags;
  335         bool inverted;
  336 
  337         sc = device_get_softc(dev);
  338         if (pin >= sc->gpio_npins)
  339                 return (EINVAL);
  340 
  341         GPIO_LOCK(sc);
  342         tmp = sc->gpio_pins[pin]->pin_ctrl_reg;
  343         GPIO_UNLOCK(sc);
  344         iosf = (tmp >> AS3722_GPIO_IOSF_SHIFT) & AS3722_GPIO_IOSF_MASK;
  345         mode = (tmp >> AS3722_GPIO_MODE_SHIFT) & AS3722_GPIO_MODE_MASK;
  346         inverted = (tmp & AS3722_GPIO_INVERT) != 0;
  347         /* Is pin in GPIO mode ? */
  348         if (iosf != AS3722_IOSF_GPIO)
  349                 return (ENXIO);
  350 
  351         flags = 0;
  352         switch (mode) {
  353         case AS3722_MODE_INPUT:
  354                 flags = GPIO_PIN_INPUT;
  355                 break;
  356         case AS3722_MODE_PUSH_PULL:
  357         case AS3722_MODE_PUSH_PULL_LV:
  358                 flags = GPIO_PIN_OUTPUT;
  359                 break;
  360         case AS3722_MODE_OPEN_DRAIN:
  361         case AS3722_MODE_OPEN_DRAIN_LV:
  362                 flags = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN;
  363                 break;
  364         case AS3722_MODE_TRISTATE:
  365                 flags = GPIO_PIN_TRISTATE;
  366                 break;
  367         case AS3722_MODE_INPUT_PULL_UP_LV:
  368                 flags = GPIO_PIN_INPUT | GPIO_PIN_PULLUP;
  369                 break;
  370 
  371         case AS3722_MODE_INPUT_PULL_DOWN:
  372                 flags = GPIO_PIN_OUTPUT | GPIO_PIN_PULLDOWN;
  373                 break;
  374         }
  375         if (inverted)
  376                 flags |= GPIO_PIN_INVIN | GPIO_PIN_INVOUT;
  377         *out_flags = flags;
  378         return (0);
  379 }
  380 
  381 static int
  382 as3722_gpio_get_mode(struct as3722_softc *sc, uint32_t pin, uint32_t gpio_flags)
  383 {
  384         uint8_t ctrl;
  385         int flags;
  386 
  387         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
  388         flags =  sc->gpio_pins[pin]->pin_cfg_flags;
  389 
  390         /* Tristate mode. */
  391         if (flags & AS3722_CFG_BIAS_HIGH_IMPEDANCE ||
  392             gpio_flags & GPIO_PIN_TRISTATE)
  393                 return (AS3722_MODE_TRISTATE);
  394 
  395         /* Open drain modes. */
  396         if (flags & AS3722_CFG_OPEN_DRAIN || gpio_flags & GPIO_PIN_OPENDRAIN) {
  397                 /* Only pull up have effect */
  398                 if (flags & AS3722_CFG_BIAS_PULL_UP ||
  399                     gpio_flags & GPIO_PIN_PULLUP)
  400                         return (AS3722_MODE_OPEN_DRAIN_LV);
  401                 return (AS3722_MODE_OPEN_DRAIN);
  402         }
  403         /* Input modes. */
  404         if (gpio_flags & GPIO_PIN_INPUT) {
  405                 /* Accept pull up or pull down. */
  406                 if (flags & AS3722_CFG_BIAS_PULL_UP ||
  407                     gpio_flags & GPIO_PIN_PULLUP)
  408                         return (AS3722_MODE_INPUT_PULL_UP_LV);
  409 
  410                 if (flags & AS3722_CFG_BIAS_PULL_DOWN ||
  411                     gpio_flags & GPIO_PIN_PULLDOWN)
  412                         return (AS3722_MODE_INPUT_PULL_DOWN);
  413                 return (AS3722_MODE_INPUT);
  414         }
  415         /*
  416          * Output modes.
  417          * Pull down is used as indicator of low voltage output.
  418          */
  419         if (flags & AS3722_CFG_BIAS_PULL_DOWN ||
  420                     gpio_flags & GPIO_PIN_PULLDOWN)
  421                 return (AS3722_MODE_PUSH_PULL_LV);
  422         return (AS3722_MODE_PUSH_PULL);
  423 }
  424 
  425 int
  426 as3722_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  427 {
  428         struct as3722_softc *sc;
  429         uint8_t ctrl, mode, iosf;
  430         int rv;
  431 
  432         sc = device_get_softc(dev);
  433         if (pin >= sc->gpio_npins)
  434                 return (EINVAL);
  435 
  436         GPIO_LOCK(sc);
  437         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
  438         iosf = (ctrl >> AS3722_GPIO_IOSF_SHIFT) & AS3722_GPIO_IOSF_MASK;
  439         /* Is pin in GPIO mode ? */
  440         if (iosf != AS3722_IOSF_GPIO) {
  441                 GPIO_UNLOCK(sc);
  442                 return (ENXIO);
  443         }
  444         mode = as3722_gpio_get_mode(sc, pin, flags);
  445         ctrl &= ~(AS3722_GPIO_MODE_MASK << AS3722_GPIO_MODE_SHIFT);
  446         ctrl |= mode << AS3722_GPIO_MODE_SHIFT;
  447         rv = 0;
  448         if (ctrl != sc->gpio_pins[pin]->pin_ctrl_reg) {
  449                 rv = WR1(sc, AS3722_GPIO0_CONTROL + pin, ctrl);
  450                 sc->gpio_pins[pin]->pin_ctrl_reg = ctrl;
  451         }
  452         GPIO_UNLOCK(sc);
  453         return (rv);
  454 }
  455 
  456 int
  457 as3722_gpio_pin_set(device_t dev, uint32_t pin, uint32_t val)
  458 {
  459         struct as3722_softc *sc;
  460         uint8_t tmp;
  461         int rv;
  462 
  463         sc = device_get_softc(dev);
  464         if (pin >= sc->gpio_npins)
  465                 return (EINVAL);
  466 
  467         tmp =  (val != 0) ? 1 : 0;
  468         if (sc->gpio_pins[pin]->pin_ctrl_reg & AS3722_GPIO_INVERT)
  469                 tmp ^= 1;
  470 
  471         GPIO_LOCK(sc);
  472         rv = RM1(sc, AS3722_GPIO_SIGNAL_OUT, (1 << pin), (tmp << pin));
  473         GPIO_UNLOCK(sc);
  474         return (rv);
  475 }
  476 
  477 int
  478 as3722_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *val)
  479 {
  480         struct as3722_softc *sc;
  481         uint8_t tmp, mode, ctrl;
  482         int rv;
  483 
  484         sc = device_get_softc(dev);
  485         if (pin >= sc->gpio_npins)
  486                 return (EINVAL);
  487 
  488         GPIO_LOCK(sc);
  489         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
  490         mode = (ctrl >> AS3722_GPIO_MODE_SHIFT) & AS3722_GPIO_MODE_MASK;
  491         if ((mode == AS3722_MODE_PUSH_PULL) ||
  492             (mode == AS3722_MODE_PUSH_PULL_LV))
  493                 rv = RD1(sc, AS3722_GPIO_SIGNAL_OUT, &tmp);
  494         else
  495                 rv = RD1(sc, AS3722_GPIO_SIGNAL_IN, &tmp);
  496         GPIO_UNLOCK(sc);
  497         if (rv != 0)
  498                 return (rv);
  499 
  500         *val = tmp & (1 << pin) ? 1 : 0;
  501         if (ctrl & AS3722_GPIO_INVERT)
  502                 *val ^= 1;
  503         return (0);
  504 }
  505 
  506 int
  507 as3722_gpio_pin_toggle(device_t dev, uint32_t pin)
  508 {
  509         struct as3722_softc *sc;
  510         uint8_t tmp;
  511         int rv;
  512 
  513         sc = device_get_softc(dev);
  514         if (pin >= sc->gpio_npins)
  515                 return (EINVAL);
  516 
  517         GPIO_LOCK(sc);
  518         rv = RD1(sc, AS3722_GPIO_SIGNAL_OUT, &tmp);
  519         if (rv != 0) {
  520                 GPIO_UNLOCK(sc);
  521                 return (rv);
  522         }
  523         tmp ^= (1 <<pin);
  524         rv = RM1(sc, AS3722_GPIO_SIGNAL_OUT, (1 << pin), tmp);
  525         GPIO_UNLOCK(sc);
  526         return (0);
  527 }
  528 
  529 int
  530 as3722_gpio_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
  531     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
  532 {
  533 
  534         if (gcells != 2)
  535                 return (ERANGE);
  536         *pin = gpios[0];
  537         *flags= gpios[1];
  538         return (0);
  539 }
  540 
  541 int
  542 as3722_gpio_attach(struct as3722_softc *sc, phandle_t node)
  543 {
  544         struct as3722_gpio_pin *pin;
  545         int i, rv;
  546 
  547         sx_init(&sc->gpio_lock, "AS3722 GPIO lock");
  548         sc->gpio_npins = NGPIO;
  549         sc->gpio_pins = malloc(sizeof(struct as3722_gpio_pin *) *
  550             sc->gpio_npins, M_AS3722_GPIO, M_WAITOK | M_ZERO);
  551 
  552         sc->gpio_busdev = gpiobus_attach_bus(sc->dev);
  553         if (sc->gpio_busdev == NULL)
  554                 return (ENXIO);
  555         for (i = 0; i < sc->gpio_npins; i++) {
  556                 sc->gpio_pins[i] = malloc(sizeof(struct as3722_gpio_pin),
  557                     M_AS3722_GPIO, M_WAITOK | M_ZERO);
  558                 pin = sc->gpio_pins[i];
  559                 sprintf(pin->pin_name, "gpio%d", i);
  560                 pin->pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT  |
  561                     GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE |
  562                     GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN |
  563                     GPIO_PIN_INVOUT;
  564                 rv = RD1(sc, AS3722_GPIO0_CONTROL + i, &pin->pin_ctrl_reg);
  565                 if (rv != 0) {
  566                         device_printf(sc->dev,
  567                             "Cannot read configuration for pin %s\n",
  568                             sc->gpio_pins[i]->pin_name);
  569                 }
  570         }
  571         return (0);
  572 }

Cache object: 1c5f51e4de4d440b3bcb57df7d1900d8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.