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/dev/gpio/gpioow.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 /*      $OpenBSD: gpioow.c,v 1.6 2022/04/06 18:59:28 naddy Exp $        */
    2 
    3 /*
    4  * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * 1-Wire bus bit-banging through GPIO pin.
   21  */
   22 
   23 #include <sys/param.h>
   24 #include <sys/systm.h>
   25 #include <sys/device.h>
   26 #include <sys/gpio.h>
   27 
   28 #include <dev/gpio/gpiovar.h>
   29 
   30 #include <dev/onewire/onewirevar.h>
   31 
   32 #define GPIOOW_NPINS            1
   33 #define GPIOOW_PIN_DATA         0
   34 
   35 struct gpioow_softc {
   36         struct device           sc_dev;
   37 
   38         void *                  sc_gpio;
   39         struct gpio_pinmap      sc_map;
   40         int                     __map[GPIOOW_NPINS];
   41 
   42         struct onewire_bus      sc_ow_bus;
   43         struct device *         sc_ow_dev;
   44 
   45         int                     sc_data;
   46         int                     sc_dying;
   47 };
   48 
   49 int     gpioow_match(struct device *, void *, void *);
   50 void    gpioow_attach(struct device *, struct device *, void *);
   51 int     gpioow_detach(struct device *, int);
   52 int     gpioow_activate(struct device *, int);
   53 
   54 int     gpioow_ow_reset(void *);
   55 int     gpioow_ow_bit(void *, int);
   56 
   57 void    gpioow_bb_rx(void *);
   58 void    gpioow_bb_tx(void *);
   59 int     gpioow_bb_get(void *);
   60 void    gpioow_bb_set(void *, int);
   61 
   62 const struct cfattach gpioow_ca = {
   63         sizeof(struct gpioow_softc),
   64         gpioow_match,
   65         gpioow_attach,
   66         gpioow_detach,
   67         gpioow_activate
   68 };
   69 
   70 struct cfdriver gpioow_cd = {
   71         NULL, "gpioow", DV_DULL
   72 };
   73 
   74 static const struct onewire_bbops gpioow_bbops = {
   75         gpioow_bb_rx,
   76         gpioow_bb_tx,
   77         gpioow_bb_get,
   78         gpioow_bb_set
   79 };
   80 
   81 int
   82 gpioow_match(struct device *parent, void *match, void *aux)
   83 {
   84         struct cfdata *cf = match;
   85         struct gpio_attach_args *ga = aux;
   86 
   87         if (ga->ga_offset == -1)
   88                 return 0;
   89 
   90         return (strcmp(cf->cf_driver->cd_name, "gpioow") == 0);
   91 }
   92 
   93 void
   94 gpioow_attach(struct device *parent, struct device *self, void *aux)
   95 {
   96         struct gpioow_softc *sc = (struct gpioow_softc *)self;
   97         struct gpio_attach_args *ga = aux;
   98         struct onewirebus_attach_args oba;
   99         int caps;
  100 
  101         /* Check that we have enough pins */
  102         if (gpio_npins(ga->ga_mask) != GPIOOW_NPINS) {
  103                 printf(": invalid pin mask\n");
  104                 return;
  105         }
  106 
  107         /* Map pins */
  108         sc->sc_gpio = ga->ga_gpio;
  109         sc->sc_map.pm_map = sc->__map;
  110         if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
  111             &sc->sc_map)) {
  112                 printf(": can't map pins\n");
  113                 return;
  114         }
  115 
  116         /* Configure data pin */
  117         caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA);
  118         if (!(caps & GPIO_PIN_OUTPUT)) {
  119                 printf(": data pin is unable to drive output\n");
  120                 goto fail;
  121         }
  122         if (!(caps & GPIO_PIN_INPUT)) {
  123                 printf(": data pin is unable to read input\n");
  124                 goto fail;
  125         }
  126         printf(": DATA[%d]", sc->sc_map.pm_map[GPIOOW_PIN_DATA]);
  127         sc->sc_data = GPIO_PIN_OUTPUT;
  128         if (caps & GPIO_PIN_OPENDRAIN) {
  129                 printf(" open-drain");
  130                 sc->sc_data |= GPIO_PIN_OPENDRAIN;
  131         } else if ((caps & GPIO_PIN_PUSHPULL) && (caps & GPIO_PIN_TRISTATE)) {
  132                 printf(" push-pull tri-state");
  133                 sc->sc_data |= GPIO_PIN_PUSHPULL;
  134         }
  135         if (caps & GPIO_PIN_PULLUP) {
  136                 printf(" pull-up");
  137                 sc->sc_data |= GPIO_PIN_PULLUP;
  138         }
  139         gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA, sc->sc_data);
  140 
  141         printf("\n");
  142 
  143         /* Attach 1-Wire bus */
  144         sc->sc_ow_bus.bus_cookie = sc;
  145         sc->sc_ow_bus.bus_reset = gpioow_ow_reset;
  146         sc->sc_ow_bus.bus_bit = gpioow_ow_bit;
  147 
  148         bzero(&oba, sizeof(oba));
  149         oba.oba_bus = &sc->sc_ow_bus;
  150         sc->sc_ow_dev = config_found(self, &oba, onewirebus_print);
  151 
  152         return;
  153 
  154 fail:
  155         gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
  156 }
  157 
  158 int
  159 gpioow_detach(struct device *self, int flags)
  160 {
  161         struct gpioow_softc *sc = (struct gpioow_softc *)self;
  162         int rv = 0;
  163 
  164         gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
  165 
  166         if (sc->sc_ow_dev != NULL)
  167                 rv = config_detach(sc->sc_ow_dev, flags);
  168 
  169         return (rv);
  170 }
  171 
  172 int
  173 gpioow_activate(struct device *self, int act)
  174 {
  175         struct gpioow_softc *sc = (struct gpioow_softc *)self;
  176         int rv = 0;
  177 
  178         switch (act) {
  179         case DVACT_DEACTIVATE:
  180                 sc->sc_dying = 1;
  181                 if (sc->sc_ow_dev != NULL)
  182                         rv = config_deactivate(sc->sc_ow_dev);
  183                 break;
  184         }
  185 
  186         return (rv);
  187 }
  188 
  189 int
  190 gpioow_ow_reset(void *arg)
  191 {
  192         return (onewire_bb_reset(&gpioow_bbops, arg));
  193 }
  194 
  195 int
  196 gpioow_ow_bit(void *arg, int value)
  197 {
  198         return (onewire_bb_bit(&gpioow_bbops, arg, value));
  199 }
  200 
  201 void
  202 gpioow_bb_rx(void *arg)
  203 {
  204         struct gpioow_softc *sc = arg;
  205         int data = sc->sc_data;
  206 
  207         data &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
  208         data |= GPIO_PIN_INPUT;
  209         if (data & GPIO_PIN_PUSHPULL)
  210                 data |= GPIO_PIN_TRISTATE;
  211         if (sc->sc_data != data) {
  212                 sc->sc_data = data;
  213                 gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
  214                     sc->sc_data);
  215         }
  216 }
  217 
  218 void
  219 gpioow_bb_tx(void *arg)
  220 {
  221         struct gpioow_softc *sc = arg;
  222         int data = sc->sc_data;
  223 
  224         data &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
  225         data |= GPIO_PIN_OUTPUT;
  226         if (sc->sc_data != data) {
  227                 sc->sc_data = data;
  228                 gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
  229                     sc->sc_data);
  230         }
  231 }
  232 
  233 int
  234 gpioow_bb_get(void *arg)
  235 {
  236         struct gpioow_softc *sc = arg;
  237 
  238         return (gpio_pin_read(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA) ==
  239             GPIO_PIN_HIGH ? 1 : 0);
  240 }
  241 
  242 void
  243 gpioow_bb_set(void *arg, int value)
  244 {
  245         struct gpioow_softc *sc = arg;
  246 
  247         gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
  248             value ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
  249 }

Cache object: daa495571056277f6b24a126ec6e017d


[ 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.