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/powerpc/wii/wii_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) 2012 Margarida Gouveia
    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 ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   21  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   22  * 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 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD: releng/10.1/sys/powerpc/wii/wii_gpio.c 250788 2013-05-18 19:30:42Z rpaulo $");
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/module.h>
   32 #include <sys/bus.h>
   33 #include <sys/conf.h>
   34 #include <sys/kernel.h>
   35 #include <sys/malloc.h>
   36 #include <sys/rman.h>
   37 #include <sys/gpio.h>
   38 #include <sys/reboot.h>
   39 
   40 #include <machine/bus.h>
   41 #include <machine/platform.h>
   42 #include <machine/intr_machdep.h>
   43 #include <machine/resource.h>
   44 
   45 #include <powerpc/wii/wii_gpioreg.h>
   46 
   47 #include "gpio_if.h"
   48 
   49 struct wiigpio_softc {
   50         device_t                 sc_dev;
   51         struct resource         *sc_rres;
   52         bus_space_tag_t          sc_bt;
   53         bus_space_handle_t       sc_bh;
   54         int                      sc_rrid;
   55         struct mtx               sc_mtx;
   56         struct gpio_pin          sc_pins[WIIGPIO_NPINS];
   57 };
   58 
   59 
   60 #define WIIGPIO_PINBANK(_p)     ((_p) / (WIIGPIO_NPINS / 2))
   61 #define WIIGPIO_PINMASK(_p)     (1 << ((_p) % (WIIGPIO_NPINS / 2)))
   62 #define WIIGPIO_LOCK(sc)        mtx_lock(&(sc)->sc_mtx)
   63 #define WIIGPIO_UNLOCK(sc)      mtx_unlock(&(sc)->sc_mtx)
   64 
   65 static int      wiigpio_probe(device_t);
   66 static int      wiigpio_attach(device_t);
   67 static int      wiigpio_detach(device_t);
   68 static int      wiigpio_pin_max(device_t, int *);
   69 static int      wiigpio_pin_getname(device_t, uint32_t, char *);
   70 static int      wiigpio_pin_getflags(device_t, uint32_t, uint32_t *);
   71 static int      wiigpio_pin_setflags(device_t, uint32_t, uint32_t);
   72 static int      wiigpio_pin_getcaps(device_t, uint32_t, uint32_t *);
   73 static int      wiigpio_pin_get(device_t, uint32_t, unsigned int *);
   74 static int      wiigpio_pin_set(device_t, uint32_t, unsigned int);
   75 static int      wiigpio_pin_toggle(device_t, uint32_t);
   76 static void     wiigpio_shutdown(void *, int);
   77 
   78 static device_method_t wiigpio_methods[] = {
   79         /* Device interface */
   80         DEVMETHOD(device_probe,         wiigpio_probe),
   81         DEVMETHOD(device_attach,        wiigpio_attach),
   82         DEVMETHOD(device_detach,        wiigpio_detach),
   83 
   84         /* GPIO protocol */
   85         DEVMETHOD(gpio_pin_max,         wiigpio_pin_max),
   86         DEVMETHOD(gpio_pin_getname,     wiigpio_pin_getname),
   87         DEVMETHOD(gpio_pin_getflags,    wiigpio_pin_getflags),
   88         DEVMETHOD(gpio_pin_setflags,    wiigpio_pin_setflags),
   89         DEVMETHOD(gpio_pin_getcaps,     wiigpio_pin_getcaps),
   90         DEVMETHOD(gpio_pin_get,         wiigpio_pin_get),
   91         DEVMETHOD(gpio_pin_set,         wiigpio_pin_set),
   92         DEVMETHOD(gpio_pin_toggle,      wiigpio_pin_toggle),
   93 
   94         DEVMETHOD_END
   95 };
   96 
   97 static driver_t wiigpio_driver = {
   98         "wiigpio",
   99         wiigpio_methods,
  100         sizeof(struct wiigpio_softc)
  101 };
  102 
  103 static devclass_t wiigpio_devclass;
  104 
  105 DRIVER_MODULE(wiigpio, wiibus, wiigpio_driver, wiigpio_devclass, 0, 0);
  106 
  107 static __inline uint32_t
  108 wiigpio_read(struct wiigpio_softc *sc, int n)
  109 {
  110 
  111         return (bus_space_read_4(sc->sc_bt, sc->sc_bh, n * 0x20));
  112 }
  113 
  114 static __inline void
  115 wiigpio_write(struct wiigpio_softc *sc, int n, uint32_t reg)
  116 {
  117 
  118         bus_space_write_4(sc->sc_bt, sc->sc_bh, n * 0x20, reg);
  119 }
  120 
  121 static __inline uint32_t
  122 wiigpio_dir_read(struct wiigpio_softc *sc, int n)
  123 {
  124 
  125         return (bus_space_read_4(sc->sc_bt, sc->sc_bh, n * 0x20 + 4));
  126 }
  127 
  128 static __inline void
  129 wiigpio_dir_write(struct wiigpio_softc *sc, int n, uint32_t reg)
  130 {
  131 
  132         bus_space_write_4(sc->sc_bt, sc->sc_bh, n * 0x20 + 4, reg);
  133 }
  134 
  135 static int
  136 wiigpio_probe(device_t dev)
  137 {
  138         device_set_desc(dev, "Nintendo Wii GPIO");
  139 
  140         return (BUS_PROBE_NOWILDCARD);
  141 }
  142 
  143 static int
  144 wiigpio_attach(device_t dev)
  145 {
  146         struct wiigpio_softc *sc;
  147         int i;
  148         uint32_t d;
  149 
  150         sc = device_get_softc(dev);
  151         sc->sc_dev = dev;
  152         sc->sc_rrid = 0;
  153         sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  154             &sc->sc_rrid, RF_ACTIVE);
  155         if (sc->sc_rres == NULL) {
  156                 device_printf(dev, "could not alloc mem resource\n");
  157                 return (ENXIO);
  158         }
  159         sc->sc_bt = rman_get_bustag(sc->sc_rres);
  160         sc->sc_bh = rman_get_bushandle(sc->sc_rres);
  161         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  162 #ifdef WIIGPIO_DEBUG
  163         device_printf(dev, "dir bank0=0x%08x bank1=0x%08x\n",
  164             wiigpio_dir_read(sc, 0), wiigpio_dir_read(sc, 1));
  165         device_printf(dev, "val bank0=0x%08x bank1=0x%08x\n",
  166             wiigpio_read(sc, 0), wiigpio_read(sc, 1));
  167 #endif
  168         for (i = 0; i < WIIGPIO_NPINS; i++) {
  169                 sc->sc_pins[i].gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
  170                 sc->sc_pins[i].gp_pin = i;
  171                 d = wiigpio_dir_read(sc, WIIGPIO_PINBANK(i));
  172                 if (d & WIIGPIO_PINMASK(i))
  173                         sc->sc_pins[i].gp_flags = GPIO_PIN_OUTPUT;
  174                 else
  175                         sc->sc_pins[i].gp_flags = GPIO_PIN_INPUT;
  176                 snprintf(sc->sc_pins[i].gp_name, GPIOMAXNAME, "PIN %d", i);
  177 #ifdef WIIGPIO_DEBUG
  178                 device_printf(dev, "PIN %d state %d flag %s\n", i,
  179                     wiigpio_read(sc, WIIGPIO_PINBANK(i)) >> 
  180                         (i % (WIIGPIO_NPINS / 2)) & 1,
  181                     sc->sc_pins[i].gp_flags == GPIO_PIN_INPUT ?
  182                     "GPIO_PIN_INPUT" : "GPIO_PIN_OUTPUT");
  183 #endif
  184         }
  185         device_add_child(dev, "gpioc", device_get_unit(dev));
  186         device_add_child(dev, "gpiobus", device_get_unit(dev));
  187         /*
  188          * We will be responsible for powering off the system.
  189          */
  190         EVENTHANDLER_REGISTER(shutdown_final, wiigpio_shutdown, dev,
  191             SHUTDOWN_PRI_LAST);
  192 
  193         return (bus_generic_attach(dev));
  194 }
  195 
  196 static int
  197 wiigpio_detach(device_t dev)
  198 {
  199         struct wiigpio_softc *sc;
  200 
  201         sc = device_get_softc(dev);
  202         bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres);
  203         mtx_destroy(&sc->sc_mtx);
  204 
  205         return (0);
  206 }
  207 
  208 static int
  209 wiigpio_pin_max(device_t dev, int *maxpin)
  210 {
  211         
  212         *maxpin = WIIGPIO_NPINS - 1;
  213 
  214         return (0);
  215 }
  216 
  217 static int
  218 wiigpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  219 {
  220         struct wiigpio_softc *sc;
  221 
  222         if (pin >= WIIGPIO_NPINS)
  223                 return (EINVAL);
  224         sc = device_get_softc(dev);
  225         *caps = sc->sc_pins[pin].gp_caps;
  226 
  227         return (0);
  228 }
  229 
  230 static int
  231 wiigpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  232 {
  233         struct wiigpio_softc *sc;
  234         uint32_t reg;
  235 
  236         if (pin >= WIIGPIO_NPINS)
  237                 return (EINVAL);
  238         sc = device_get_softc(dev);
  239         WIIGPIO_LOCK(sc);
  240         reg = wiigpio_read(sc, WIIGPIO_PINBANK(pin));
  241         *val = !!(reg & WIIGPIO_PINMASK(pin));
  242         WIIGPIO_UNLOCK(sc);
  243 
  244         return (0);
  245 }
  246 
  247 static int
  248 wiigpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  249 {
  250         struct wiigpio_softc *sc;
  251         uint32_t reg, pinbank, pinmask;
  252 
  253         if (pin >= WIIGPIO_NPINS)
  254                 return (EINVAL);
  255         sc = device_get_softc(dev);
  256         pinbank = WIIGPIO_PINBANK(pin);
  257         pinmask = WIIGPIO_PINMASK(pin);
  258         WIIGPIO_LOCK(sc);
  259         reg = wiigpio_read(sc, pinbank) & ~pinmask;
  260         if (value)
  261                 reg |= pinmask;
  262         wiigpio_write(sc, pinbank, reg);
  263         WIIGPIO_UNLOCK(sc);
  264 
  265         return (0);
  266 }
  267 
  268 static int
  269 wiigpio_pin_toggle(device_t dev, uint32_t pin)
  270 {
  271         struct wiigpio_softc *sc;
  272         uint32_t val, pinbank, pinmask;
  273 
  274         if (pin >= WIIGPIO_NPINS)
  275                 return (EINVAL);
  276         sc = device_get_softc(dev);
  277         pinbank = WIIGPIO_PINBANK(pin);
  278         pinmask = WIIGPIO_PINMASK(pin);
  279         WIIGPIO_LOCK(sc);
  280         val = wiigpio_read(sc, pinbank);
  281         if (val & pinmask)
  282                 wiigpio_write(sc, pinbank, val & ~pinmask);
  283         else
  284                 wiigpio_write(sc, pinbank, val | pinmask);
  285         WIIGPIO_UNLOCK(sc);
  286 
  287         return (0);
  288 }
  289 
  290 static int
  291 wiigpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  292 {
  293         struct wiigpio_softc *sc;
  294         uint32_t reg, pinbank, pinmask;
  295 
  296         if (pin >= WIIGPIO_NPINS)
  297                 return (EINVAL);
  298         if ((flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) != 0)
  299                 return (EINVAL);
  300         if ((flags & (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) == 
  301             (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT))
  302                 return (EINVAL);
  303         sc = device_get_softc(dev);
  304         pinbank = WIIGPIO_PINBANK(pin);
  305         pinmask = WIIGPIO_PINMASK(pin);
  306         WIIGPIO_LOCK(sc);
  307         reg = wiigpio_dir_read(sc, WIIGPIO_PINBANK(pin));
  308         if (flags & GPIO_PIN_OUTPUT)
  309                 wiigpio_dir_write(sc, pinbank, reg | pinmask);
  310         else
  311                 wiigpio_dir_write(sc, pinbank, reg & ~pinmask);
  312         sc->sc_pins[pin].gp_flags = flags;
  313         WIIGPIO_UNLOCK(sc);
  314 
  315         return (0);
  316 }
  317 
  318 static int
  319 wiigpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  320 {
  321         struct wiigpio_softc *sc;
  322 
  323         if (pin >= WIIGPIO_NPINS)
  324                 return (EINVAL);
  325         sc = device_get_softc(dev);
  326         WIIGPIO_LOCK(sc);
  327         *flags = sc->sc_pins[pin].gp_flags;
  328         WIIGPIO_UNLOCK(sc);
  329 
  330         return (0);
  331 }
  332 
  333 static int
  334 wiigpio_pin_getname(device_t dev, uint32_t pin, char *name)
  335 {
  336         struct wiigpio_softc *sc;
  337 
  338         if (pin >= WIIGPIO_NPINS)
  339                 return (EINVAL);
  340         sc = device_get_softc(dev);
  341         WIIGPIO_LOCK(sc);
  342         memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
  343         WIIGPIO_UNLOCK(sc);
  344 
  345         return (0);
  346 }
  347 
  348 static void
  349 wiigpio_shutdown(void *xdev, int howto)
  350 {
  351         device_t dev;
  352 
  353         if (!(howto & RB_POWEROFF))
  354                 return;
  355         dev = (device_t)xdev;
  356         wiigpio_pin_setflags(dev, WIIGPIO_POWEROFF_PIN, GPIO_PIN_OUTPUT);
  357         wiigpio_pin_set(dev, WIIGPIO_POWEROFF_PIN, 1);
  358 }

Cache object: 00215c49821d9b65bd3dbc13882e3988


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