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/mips/ingenic/jz4780_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 2015 Alexander Kabaev <kan@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 "opt_platform.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/conf.h>
   35 #include <sys/bus.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/lock.h>
   39 #include <sys/mutex.h>
   40 #include <sys/proc.h>
   41 #include <sys/resource.h>
   42 #include <sys/gpio.h>
   43 
   44 #include <machine/bus.h>
   45 #include <machine/intr.h>
   46 
   47 #include <dev/gpio/gpiobusvar.h>
   48 
   49 #include <dev/fdt/fdt_common.h>
   50 #include <dev/ofw/ofw_bus.h>
   51 #include <dev/ofw/ofw_bus_subr.h>
   52 
   53 #include <mips/ingenic/jz4780_regs.h>
   54 #include <dt-bindings/interrupt-controller/irq.h>
   55 
   56 #include "jz4780_gpio_if.h"
   57 #include "gpio_if.h"
   58 #include "pic_if.h"
   59 
   60 #define JZ4780_GPIO_PINS 32
   61 
   62 enum pin_function {
   63         JZ_FUNC_DEV_0,
   64         JZ_FUNC_DEV_1,
   65         JZ_FUNC_DEV_2,
   66         JZ_FUNC_DEV_3,
   67         JZ_FUNC_GPIO,
   68         JZ_FUNC_INTR,
   69 };
   70 
   71 struct jz4780_gpio_pin {
   72         struct intr_irqsrc pin_irqsrc;
   73         enum intr_trigger intr_trigger;
   74         enum intr_polarity intr_polarity;
   75         enum pin_function pin_func;
   76         uint32_t pin_caps;
   77         uint32_t pin_flags;
   78         uint32_t pin_num;
   79         char pin_name[GPIOMAXNAME];
   80 };
   81 
   82 struct jz4780_gpio_softc {
   83         device_t                dev;
   84         device_t                busdev;
   85         struct resource         *res[2];
   86         struct mtx              mtx;
   87         struct jz4780_gpio_pin  pins[JZ4780_GPIO_PINS];
   88         void                    *intrhand;
   89 };
   90 
   91 static struct resource_spec jz4780_gpio_spec[] = {
   92         { SYS_RES_MEMORY, 0, RF_ACTIVE },
   93         { SYS_RES_IRQ,    0, RF_ACTIVE },
   94         { -1, 0 }
   95 };
   96 
   97 static int jz4780_gpio_probe(device_t dev);
   98 static int jz4780_gpio_attach(device_t dev);
   99 static int jz4780_gpio_detach(device_t dev);
  100 static int jz4780_gpio_intr(void *arg);
  101 
  102 #define JZ4780_GPIO_LOCK(sc)            mtx_lock_spin(&(sc)->mtx)
  103 #define JZ4780_GPIO_UNLOCK(sc)          mtx_unlock_spin(&(sc)->mtx)
  104 #define JZ4780_GPIO_LOCK_INIT(sc)       \
  105     mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),        \
  106     "jz4780_gpio", MTX_SPIN)
  107 #define JZ4780_GPIO_LOCK_DESTROY(sc)    mtx_destroy(&(sc)->mtx);
  108 
  109 #define CSR_WRITE_4(sc, reg, val)       bus_write_4((sc)->res[0], (reg), (val))
  110 #define CSR_READ_4(sc, reg)             bus_read_4((sc)->res[0], (reg))
  111 
  112 static int
  113 jz4780_gpio_probe(device_t dev)
  114 {
  115         phandle_t node;
  116 
  117         if (!ofw_bus_status_okay(dev))
  118                 return (ENXIO);
  119 
  120         /* We only like particular parent */
  121         if (!ofw_bus_is_compatible(device_get_parent(dev),
  122            "ingenic,jz4780-pinctrl"))
  123                 return (ENXIO);
  124 
  125         /* ... and only specific children os that parent */
  126         node = ofw_bus_get_node(dev);
  127         if (!OF_hasprop(node, "gpio-controller"))
  128                 return (ENXIO);
  129 
  130         device_set_desc(dev, "Ingenic JZ4780 GPIO Controller");
  131 
  132         return (BUS_PROBE_DEFAULT);
  133 }
  134 
  135 static int
  136 jz4780_gpio_pin_set_func(struct jz4780_gpio_softc *sc, uint32_t pin,
  137     uint32_t func)
  138 {
  139         uint32_t mask = (1u << pin);
  140 
  141         if (func > (uint32_t)JZ_FUNC_DEV_3)
  142                 return (EINVAL);
  143 
  144         CSR_WRITE_4(sc, JZ_GPIO_INTC, mask);
  145         CSR_WRITE_4(sc, JZ_GPIO_MASKC, mask);
  146         if (func & 2)
  147                 CSR_WRITE_4(sc, JZ_GPIO_PAT1S, mask);
  148         else
  149                 CSR_WRITE_4(sc, JZ_GPIO_PAT1C, mask);
  150         if (func & 1)
  151                 CSR_WRITE_4(sc, JZ_GPIO_PAT0S, mask);
  152         else
  153                 CSR_WRITE_4(sc, JZ_GPIO_PAT0C, mask);
  154 
  155         sc->pins[pin].pin_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
  156         sc->pins[pin].pin_func = (enum pin_function)func;
  157         return (0);
  158 }
  159 
  160 static int
  161 jz4780_gpio_pin_set_direction(struct jz4780_gpio_softc *sc,
  162     uint32_t pin, uint32_t dir)
  163 {
  164         uint32_t mask = (1u << pin);
  165 
  166         switch (dir) {
  167         case GPIO_PIN_OUTPUT:
  168                 if (sc->pins[pin].pin_caps & dir)
  169                         CSR_WRITE_4(sc, JZ_GPIO_PAT1C, mask);
  170                 else
  171                         return (EINVAL);
  172                 break;
  173         case GPIO_PIN_INPUT:
  174                 if (sc->pins[pin].pin_caps & dir)
  175                         CSR_WRITE_4(sc, JZ_GPIO_PAT1S, mask);
  176                 else
  177                         return (EINVAL);
  178                 break;
  179         }
  180 
  181         sc->pins[pin].pin_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
  182         sc->pins[pin].pin_flags |= dir;
  183         return (0);
  184 }
  185 
  186 static int
  187 jz4780_gpio_pin_set_bias(struct jz4780_gpio_softc *sc,
  188     uint32_t pin, uint32_t bias)
  189 {
  190         uint32_t mask = (1u << pin);
  191 
  192         switch (bias) {
  193         case GPIO_PIN_PULLUP:
  194         case GPIO_PIN_PULLDOWN:
  195                 if (sc->pins[pin].pin_caps & bias)
  196                         CSR_WRITE_4(sc, JZ_GPIO_DPULLC, mask);
  197                 else
  198                         return (EINVAL);
  199                 break;
  200         case 0:
  201                 CSR_WRITE_4(sc, JZ_GPIO_DPULLS, mask);
  202                 break;
  203         default:
  204                 return (ENOTSUP);
  205         }
  206 
  207         sc->pins[pin].pin_flags &= ~(GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
  208         sc->pins[pin].pin_flags |= bias;
  209         return (0);
  210 }
  211 
  212 /*
  213  * Decode pin configuration using this map
  214  */
  215 #if 0
  216 INT MASK PAT1 PAT0
  217 1   x    0    0 /* intr, level, low */
  218 1   x    0    1 /* intr, level, high */
  219 1   x    1    0 /* intr, edge, falling */
  220 1   x    1    1 /* intr, edge, rising */
  221 0   0    0    0 /* function, func 0 */
  222 0   0    0    1 /* function, func 1 */
  223 0   0    1    0 /* function, func 2 */
  224 0   0    1    0 /* function, func 3 */
  225 0   1    0    0 /* gpio, output 0 */
  226 0   1    0    1 /* gpio, output 1 */
  227 0   1    1    x /* gpio, input */
  228 #endif
  229 
  230 static void
  231 jz4780_gpio_pin_probe(struct jz4780_gpio_softc *sc, uint32_t pin)
  232 {
  233         uint32_t mask = (1u << pin);
  234         uint32_t val;
  235 
  236         /* Clear cached gpio config */
  237         sc->pins[pin].pin_flags = 0;
  238 
  239         /* First check if pin is in interrupt mode */
  240         val = CSR_READ_4(sc, JZ_GPIO_INT);
  241         if (val & mask) {
  242                 /* Pin is in interrupt mode, decode interrupt triggering mode */
  243                 val = CSR_READ_4(sc, JZ_GPIO_PAT1);
  244                 if (val & mask)
  245                         sc->pins[pin].intr_trigger = INTR_TRIGGER_EDGE;
  246                 else
  247                         sc->pins[pin].intr_trigger = INTR_TRIGGER_LEVEL;
  248                 /* Decode interrupt polarity */
  249                 val = CSR_READ_4(sc, JZ_GPIO_PAT0);
  250                 if (val & mask)
  251                         sc->pins[pin].intr_polarity = INTR_POLARITY_HIGH;
  252                 else
  253                         sc->pins[pin].intr_polarity = INTR_POLARITY_LOW;
  254 
  255                 sc->pins[pin].pin_func = JZ_FUNC_INTR;
  256                 sc->pins[pin].pin_flags = 0;
  257                 return;
  258         }
  259         /* Next check if pin is in gpio mode */
  260         val = CSR_READ_4(sc, JZ_GPIO_MASK);
  261         if (val & mask) {
  262                 /* Pin is in gpio mode, decode direction and bias */
  263                 val = CSR_READ_4(sc, JZ_GPIO_PAT1);
  264                 if (val & mask)
  265                         sc->pins[pin].pin_flags |= GPIO_PIN_INPUT;
  266                 else
  267                         sc->pins[pin].pin_flags |= GPIO_PIN_OUTPUT;
  268                 /* Check for bias */
  269                 val = CSR_READ_4(sc, JZ_GPIO_DPULL);
  270                 if ((val & mask) == 0)
  271                         sc->pins[pin].pin_flags |= sc->pins[pin].pin_caps &
  272                                 (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
  273                 sc->pins[pin].pin_func = JZ_FUNC_GPIO;
  274                 return;
  275         }
  276         /* By exclusion, pin is in alternate function mode */
  277         val = CSR_READ_4(sc, JZ_GPIO_DPULL);
  278         if ((val & mask) == 0)
  279                 sc->pins[pin].pin_flags = sc->pins[pin].pin_caps &
  280                         (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
  281         val = ((CSR_READ_4(sc, JZ_GPIO_PAT1) & mask) >> pin) << 1;
  282         val = val | ((CSR_READ_4(sc, JZ_GPIO_PAT1) & mask) >> pin);
  283         sc->pins[pin].pin_func = (enum pin_function)val;
  284 }
  285 
  286 static int
  287 jz4780_gpio_register_isrcs(struct jz4780_gpio_softc *sc)
  288 {
  289         int error;
  290         uint32_t irq, i;
  291         struct intr_irqsrc *isrc;
  292         const char *name;
  293 
  294         name = device_get_nameunit(sc->dev);
  295         for (irq = 0; irq < JZ4780_GPIO_PINS; irq++) {
  296                 isrc = &sc->pins[irq].pin_irqsrc;
  297                 error = intr_isrc_register(isrc, sc->dev, 0, "%s,%d",
  298                     name, irq);
  299                 if (error != 0) {
  300                         for (i = 0; i < irq; i++)
  301                                 intr_isrc_deregister(&sc->pins[i].pin_irqsrc);
  302                         device_printf(sc->dev, "%s failed", __func__);
  303                         return (error);
  304                 }
  305         }
  306 
  307         return (0);
  308 }
  309 
  310 static int
  311 jz4780_gpio_attach(device_t dev)
  312 {
  313         struct jz4780_gpio_softc *sc = device_get_softc(dev);
  314         phandle_t node;
  315         uint32_t i, pd_pins, pu_pins;
  316 
  317         sc->dev = dev;
  318 
  319         if (bus_alloc_resources(dev, jz4780_gpio_spec, sc->res)) {
  320                 device_printf(dev, "could not allocate resources for device\n");
  321                 return (ENXIO);
  322         }
  323 
  324         JZ4780_GPIO_LOCK_INIT(sc);
  325 
  326         node = ofw_bus_get_node(dev);
  327         OF_getencprop(node, "ingenic,pull-ups", &pu_pins, sizeof(pu_pins));
  328         OF_getencprop(node, "ingenic,pull-downs", &pd_pins, sizeof(pd_pins));
  329 
  330         for (i = 0; i < JZ4780_GPIO_PINS; i++) {
  331                 sc->pins[i].pin_num = i;
  332                 sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
  333                 if (pu_pins & (1 << i))
  334                         sc->pins[i].pin_caps |= GPIO_PIN_PULLUP;
  335                 if (pd_pins & (1 << i))
  336                         sc->pins[i].pin_caps |= GPIO_PIN_PULLDOWN;
  337                 sc->pins[i].intr_polarity = INTR_POLARITY_CONFORM;
  338                 sc->pins[i].intr_trigger = INTR_TRIGGER_CONFORM;
  339 
  340                 snprintf(sc->pins[i].pin_name, GPIOMAXNAME - 1, "gpio%c%d",
  341                     device_get_unit(dev) + 'a', i);
  342                 sc->pins[i].pin_name[GPIOMAXNAME - 1] = '\0';
  343 
  344                 jz4780_gpio_pin_probe(sc, i);
  345         }
  346 
  347         if (jz4780_gpio_register_isrcs(sc) != 0)
  348                 goto fail;
  349 
  350         if (intr_pic_register(dev, OF_xref_from_node(node)) == NULL) {
  351                 device_printf(dev, "could not register PIC\n");
  352                 goto fail;
  353         }
  354 
  355         if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
  356             jz4780_gpio_intr, NULL, sc, &sc->intrhand) != 0)
  357                 goto fail_pic;
  358 
  359         sc->busdev = gpiobus_attach_bus(dev);
  360         if (sc->busdev == NULL)
  361                 goto fail_pic;
  362 
  363         return (0);
  364 fail_pic:
  365         intr_pic_deregister(dev, OF_xref_from_node(node));
  366 fail:
  367         if (sc->intrhand != NULL)
  368                 bus_teardown_intr(dev, sc->res[1], sc->intrhand);
  369         bus_release_resources(dev, jz4780_gpio_spec, sc->res);
  370         JZ4780_GPIO_LOCK_DESTROY(sc);
  371         return (ENXIO);
  372 }
  373 
  374 static int
  375 jz4780_gpio_detach(device_t dev)
  376 {
  377         struct jz4780_gpio_softc *sc = device_get_softc(dev);
  378 
  379         bus_release_resources(dev, jz4780_gpio_spec, sc->res);
  380         JZ4780_GPIO_LOCK_DESTROY(sc);
  381         return (0);
  382 }
  383 
  384 static int
  385 jz4780_gpio_configure_pin(device_t dev, uint32_t pin, uint32_t func,
  386     uint32_t flags)
  387 {
  388         struct jz4780_gpio_softc *sc;
  389         int retval;
  390 
  391         if (pin >= JZ4780_GPIO_PINS)
  392                 return (EINVAL);
  393 
  394         sc = device_get_softc(dev);
  395         JZ4780_GPIO_LOCK(sc);
  396         retval = jz4780_gpio_pin_set_func(sc, pin, func);
  397         if (retval == 0)
  398                 retval = jz4780_gpio_pin_set_bias(sc, pin, flags);
  399         JZ4780_GPIO_UNLOCK(sc);
  400         return (retval);
  401 }
  402 
  403 static device_t
  404 jz4780_gpio_get_bus(device_t dev)
  405 {
  406         struct jz4780_gpio_softc *sc;
  407 
  408         sc = device_get_softc(dev);
  409 
  410         return (sc->busdev);
  411 }
  412 
  413 static int
  414 jz4780_gpio_pin_max(device_t dev, int *maxpin)
  415 {
  416 
  417         *maxpin = JZ4780_GPIO_PINS - 1;
  418         return (0);
  419 }
  420 
  421 static int
  422 jz4780_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  423 {
  424         struct jz4780_gpio_softc *sc;
  425 
  426         if (pin >= JZ4780_GPIO_PINS)
  427                 return (EINVAL);
  428 
  429         sc = device_get_softc(dev);
  430         JZ4780_GPIO_LOCK(sc);
  431         *caps = sc->pins[pin].pin_caps;
  432         JZ4780_GPIO_UNLOCK(sc);
  433 
  434         return (0);
  435 }
  436 
  437 static int
  438 jz4780_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  439 {
  440         struct jz4780_gpio_softc *sc;
  441 
  442         if (pin >= JZ4780_GPIO_PINS)
  443                 return (EINVAL);
  444 
  445         sc = device_get_softc(dev);
  446         JZ4780_GPIO_LOCK(sc);
  447         *flags = sc->pins[pin].pin_flags;
  448         JZ4780_GPIO_UNLOCK(sc);
  449 
  450         return (0);
  451 }
  452 
  453 static int
  454 jz4780_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  455 {
  456         struct jz4780_gpio_softc *sc;
  457 
  458         if (pin >= JZ4780_GPIO_PINS)
  459                 return (EINVAL);
  460 
  461         sc = device_get_softc(dev);
  462         strncpy(name, sc->pins[pin].pin_name, GPIOMAXNAME - 1);
  463         name[GPIOMAXNAME - 1] = '\0';
  464 
  465         return (0);
  466 }
  467 
  468 static int
  469 jz4780_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  470 {
  471         struct jz4780_gpio_softc *sc;
  472         int retval;
  473 
  474         if (pin >= JZ4780_GPIO_PINS)
  475                 return (EINVAL);
  476 
  477         sc = device_get_softc(dev);
  478         JZ4780_GPIO_LOCK(sc);
  479         retval = jz4780_gpio_pin_set_direction(sc, pin,
  480             flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT));
  481         if (retval == 0)
  482                 retval = jz4780_gpio_pin_set_bias(sc, pin,
  483                     flags & (GPIO_PIN_PULLDOWN | GPIO_PIN_PULLUP));
  484         JZ4780_GPIO_UNLOCK(sc);
  485 
  486         return (retval);
  487 }
  488 
  489 static int
  490 jz4780_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  491 {
  492         struct jz4780_gpio_softc *sc;
  493         uint32_t mask;
  494         int retval;
  495 
  496         if (pin >= JZ4780_GPIO_PINS)
  497                 return (EINVAL);
  498 
  499         retval = EINVAL;
  500         mask = (1u << pin);
  501         sc = device_get_softc(dev);
  502         JZ4780_GPIO_LOCK(sc);
  503         if (sc->pins[pin].pin_func == JZ_FUNC_GPIO) {
  504                 CSR_WRITE_4(sc, value ? JZ_GPIO_PAT0S : JZ_GPIO_PAT0C, mask);
  505                 retval = 0;
  506         }
  507         JZ4780_GPIO_UNLOCK(sc);
  508 
  509         return (retval);
  510 }
  511 
  512 static int
  513 jz4780_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  514 {
  515         struct jz4780_gpio_softc *sc;
  516         uint32_t data, mask;
  517 
  518         if (pin >= JZ4780_GPIO_PINS)
  519                 return (EINVAL);
  520 
  521         mask = (1u << pin);
  522         sc = device_get_softc(dev);
  523         JZ4780_GPIO_LOCK(sc);
  524         data = CSR_READ_4(sc, JZ_GPIO_PIN);
  525         JZ4780_GPIO_UNLOCK(sc);
  526         *val = (data & mask) ? 1 : 0;
  527 
  528         return (0);
  529 }
  530 
  531 static int
  532 jz4780_gpio_pin_toggle(device_t dev, uint32_t pin)
  533 {
  534         struct jz4780_gpio_softc *sc;
  535         uint32_t data, mask;
  536         int retval;
  537 
  538         if (pin >= JZ4780_GPIO_PINS)
  539                 return (EINVAL);
  540 
  541         retval = EINVAL;
  542         mask = (1u << pin);
  543         sc = device_get_softc(dev);
  544         JZ4780_GPIO_LOCK(sc);
  545         if (sc->pins[pin].pin_func == JZ_FUNC_GPIO &&
  546             sc->pins[pin].pin_flags & GPIO_PIN_OUTPUT) {
  547                 data = CSR_READ_4(sc, JZ_GPIO_PIN);
  548                 CSR_WRITE_4(sc, (data & mask) ? JZ_GPIO_PAT0C : JZ_GPIO_PAT0S,
  549                     mask);
  550                 retval = 0;
  551         }
  552         JZ4780_GPIO_UNLOCK(sc);
  553 
  554         return (retval);
  555 }
  556 
  557 #ifdef FDT
  558 static int
  559 jz_gpio_map_intr_fdt(device_t dev, struct intr_map_data *data, u_int *irqp,
  560         enum intr_polarity *polp, enum intr_trigger *trigp)
  561 {
  562         struct jz4780_gpio_softc *sc;
  563         struct intr_map_data_fdt *daf;
  564 
  565         sc = device_get_softc(dev);
  566         daf = (struct intr_map_data_fdt *)data;
  567 
  568         if (data == NULL || data->type != INTR_MAP_DATA_FDT ||
  569             daf->ncells == 0 || daf->ncells > 2)
  570                 return (EINVAL);
  571 
  572         *irqp = daf->cells[0];
  573         if (daf->ncells == 1) {
  574                 *trigp = INTR_TRIGGER_CONFORM;
  575                 *polp = INTR_POLARITY_CONFORM;
  576                 return (0);
  577         }
  578 
  579         switch (daf->cells[1])
  580         {
  581         case IRQ_TYPE_EDGE_RISING:
  582                 *trigp = INTR_TRIGGER_EDGE;
  583                 *polp = INTR_POLARITY_HIGH;
  584                 break;
  585         case IRQ_TYPE_EDGE_FALLING:
  586                 *trigp = INTR_TRIGGER_EDGE;
  587                 *polp = INTR_POLARITY_LOW;
  588                 break;
  589         case IRQ_TYPE_LEVEL_HIGH:
  590                 *trigp = INTR_TRIGGER_LEVEL;
  591                 *polp = INTR_POLARITY_HIGH;
  592                 break;
  593         case IRQ_TYPE_LEVEL_LOW:
  594                 *trigp = INTR_TRIGGER_LEVEL;
  595                 *polp = INTR_POLARITY_LOW;
  596                 break;
  597         default:
  598                 device_printf(sc->dev, "unsupported trigger/polarity 0x%2x\n",
  599                     daf->cells[1]);
  600                 return (ENOTSUP);
  601         }
  602 
  603         return (0);
  604 }
  605 #endif
  606 
  607 static int
  608 jz_gpio_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp,
  609         enum intr_polarity *polp, enum intr_trigger *trigp)
  610 {
  611         struct jz4780_gpio_softc *sc;
  612         enum intr_polarity pol;
  613         enum intr_trigger trig;
  614         u_int irq;
  615 
  616         sc = device_get_softc(dev);
  617         switch (data->type) {
  618 #ifdef FDT
  619         case INTR_MAP_DATA_FDT:
  620                 if (jz_gpio_map_intr_fdt(dev, data, &irq, &pol, &trig) != 0)
  621                         return (EINVAL);
  622                 break;
  623 #endif
  624         default:
  625                 return (EINVAL);
  626         }
  627 
  628         if (irq >= nitems(sc->pins))
  629                 return (EINVAL);
  630 
  631         *irqp = irq;
  632         if (polp != NULL)
  633                 *polp = pol;
  634         if (trigp != NULL)
  635                 *trigp = trig;
  636         return (0);
  637 }
  638 
  639 static int
  640 jz4780_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
  641     struct intr_irqsrc **isrcp)
  642 {
  643         struct jz4780_gpio_softc *sc;
  644         int retval;
  645         u_int irq;
  646 
  647         retval = jz_gpio_map_intr(dev, data, &irq, NULL, NULL);
  648         if (retval == 0) {
  649                 sc = device_get_softc(dev);
  650                 *isrcp = &sc->pins[irq].pin_irqsrc;
  651         }
  652         return (retval);
  653 }
  654 
  655 static int
  656 jz4780_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
  657         struct resource *res, struct intr_map_data *data)
  658 {
  659         struct jz4780_gpio_softc *sc;
  660         struct jz4780_gpio_pin *pin;
  661         enum intr_polarity pol;
  662         enum intr_trigger trig;
  663         uint32_t mask, irq;
  664 
  665         if (data == NULL)
  666                 return (ENOTSUP);
  667 
  668         /* Get config for resource. */
  669         if (jz_gpio_map_intr(dev, data, &irq, &pol, &trig))
  670                 return (EINVAL);
  671 
  672         pin = __containerof(isrc, struct jz4780_gpio_pin, pin_irqsrc);
  673         if (isrc != &pin->pin_irqsrc)
  674                 return (EINVAL);
  675 
  676         /* Compare config if this is not first setup. */
  677         if (isrc->isrc_handlers != 0) {
  678                 if ((pol != INTR_POLARITY_CONFORM && pol != pin->intr_polarity) ||
  679                     (trig != INTR_TRIGGER_CONFORM && trig != pin->intr_trigger))
  680                         return (EINVAL);
  681                 else
  682                         return (0);
  683         }
  684 
  685         if (pol == INTR_POLARITY_CONFORM)
  686                 pol = INTR_POLARITY_LOW;        /* just pick some */
  687         if (trig == INTR_TRIGGER_CONFORM)
  688                 trig = INTR_TRIGGER_EDGE;       /* just pick some */
  689 
  690         sc = device_get_softc(dev);
  691         mask = 1u << pin->pin_num;
  692 
  693         JZ4780_GPIO_LOCK(sc);
  694         CSR_WRITE_4(sc, JZ_GPIO_MASKS, mask);
  695         CSR_WRITE_4(sc, JZ_GPIO_INTS, mask);
  696 
  697         if (trig == INTR_TRIGGER_LEVEL)
  698                 CSR_WRITE_4(sc, JZ_GPIO_PAT1C, mask);
  699         else
  700                 CSR_WRITE_4(sc, JZ_GPIO_PAT1S, mask);
  701 
  702         if (pol == INTR_POLARITY_LOW)
  703                 CSR_WRITE_4(sc, JZ_GPIO_PAT0C, mask);
  704         else
  705                 CSR_WRITE_4(sc, JZ_GPIO_PAT0S, mask);
  706 
  707         pin->pin_func = JZ_FUNC_INTR;
  708         pin->intr_trigger = trig;
  709         pin->intr_polarity = pol;
  710 
  711         CSR_WRITE_4(sc, JZ_GPIO_FLAGC, mask);
  712         CSR_WRITE_4(sc, JZ_GPIO_MASKC, mask);
  713         JZ4780_GPIO_UNLOCK(sc);
  714         return (0);
  715 }
  716 
  717 static void
  718 jz4780_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
  719 {
  720         struct jz4780_gpio_softc *sc;
  721         struct jz4780_gpio_pin *pin;
  722 
  723         sc = device_get_softc(dev);
  724         pin = __containerof(isrc, struct jz4780_gpio_pin, pin_irqsrc);
  725 
  726         CSR_WRITE_4(sc, JZ_GPIO_MASKC, 1u << pin->pin_num);
  727 }
  728 
  729 static void
  730 jz4780_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
  731 {
  732         struct jz4780_gpio_softc *sc;
  733         struct jz4780_gpio_pin *pin;
  734 
  735         sc = device_get_softc(dev);
  736         pin = __containerof(isrc, struct jz4780_gpio_pin, pin_irqsrc);
  737 
  738         CSR_WRITE_4(sc, JZ_GPIO_MASKS, 1u << pin->pin_num);
  739 }
  740 
  741 static void
  742 jz4780_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
  743 {
  744 
  745         jz4780_gpio_pic_disable_intr(dev, isrc);
  746 }
  747 
  748 static void
  749 jz4780_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
  750 {
  751 
  752         jz4780_gpio_pic_enable_intr(dev, isrc);
  753 }
  754 
  755 static void
  756 jz4780_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
  757 {
  758         struct jz4780_gpio_softc *sc;
  759         struct jz4780_gpio_pin *pin;
  760 
  761         sc = device_get_softc(dev);
  762         pin = __containerof(isrc, struct jz4780_gpio_pin, pin_irqsrc);
  763 
  764         CSR_WRITE_4(sc, JZ_GPIO_FLAGC, 1u << pin->pin_num);
  765 }
  766 
  767 static int
  768 jz4780_gpio_intr(void *arg)
  769 {
  770         struct jz4780_gpio_softc *sc;
  771         uint32_t i, interrupts;
  772 
  773         sc = arg;
  774         interrupts = CSR_READ_4(sc, JZ_GPIO_FLAG);
  775 
  776         for (i = 0; interrupts != 0; i++, interrupts >>= 1) {
  777                 if ((interrupts & 0x1) == 0)
  778                         continue;
  779                 if (intr_isrc_dispatch(&sc->pins[i].pin_irqsrc,
  780                     curthread->td_intr_frame) != 0) {
  781                         device_printf(sc->dev, "spurious interrupt %d\n", i);
  782                         PIC_DISABLE_INTR(sc->dev, &sc->pins[i].pin_irqsrc);
  783                 }
  784         }
  785 
  786         return (FILTER_HANDLED);
  787 }
  788 
  789 static phandle_t
  790 jz4780_gpio_bus_get_node(device_t bus, device_t dev)
  791 {
  792 
  793         return (ofw_bus_get_node(bus));
  794 }
  795 
  796 static device_method_t jz4780_gpio_methods[] = {
  797         /* Device interface */
  798         DEVMETHOD(device_probe,         jz4780_gpio_probe),
  799         DEVMETHOD(device_attach,        jz4780_gpio_attach),
  800         DEVMETHOD(device_detach,        jz4780_gpio_detach),
  801 
  802         /* GPIO protocol */
  803         DEVMETHOD(gpio_get_bus,         jz4780_gpio_get_bus),
  804         DEVMETHOD(gpio_pin_max,         jz4780_gpio_pin_max),
  805         DEVMETHOD(gpio_pin_getname,     jz4780_gpio_pin_getname),
  806         DEVMETHOD(gpio_pin_getflags,    jz4780_gpio_pin_getflags),
  807         DEVMETHOD(gpio_pin_getcaps,     jz4780_gpio_pin_getcaps),
  808         DEVMETHOD(gpio_pin_setflags,    jz4780_gpio_pin_setflags),
  809         DEVMETHOD(gpio_pin_get,         jz4780_gpio_pin_get),
  810         DEVMETHOD(gpio_pin_set,         jz4780_gpio_pin_set),
  811         DEVMETHOD(gpio_pin_toggle,      jz4780_gpio_pin_toggle),
  812 
  813         /* Custom interface to set pin function */
  814         DEVMETHOD(jz4780_gpio_configure_pin, jz4780_gpio_configure_pin),
  815 
  816         /* Interrupt controller interface */
  817         DEVMETHOD(pic_setup_intr,       jz4780_gpio_pic_setup_intr),
  818         DEVMETHOD(pic_enable_intr,      jz4780_gpio_pic_enable_intr),
  819         DEVMETHOD(pic_disable_intr,     jz4780_gpio_pic_disable_intr),
  820         DEVMETHOD(pic_map_intr,         jz4780_gpio_pic_map_intr),
  821         DEVMETHOD(pic_post_filter,      jz4780_gpio_pic_post_filter),
  822         DEVMETHOD(pic_post_ithread,     jz4780_gpio_pic_post_ithread),
  823         DEVMETHOD(pic_pre_ithread,      jz4780_gpio_pic_pre_ithread),
  824 
  825         /* ofw_bus interface */
  826         DEVMETHOD(ofw_bus_get_node,     jz4780_gpio_bus_get_node),
  827 
  828         DEVMETHOD_END
  829 };
  830 
  831 static driver_t jz4780_gpio_driver = {
  832         "gpio",
  833         jz4780_gpio_methods,
  834         sizeof(struct jz4780_gpio_softc),
  835 };
  836 
  837 static devclass_t jz4780_gpio_devclass;
  838 
  839 EARLY_DRIVER_MODULE(jz4780_gpio, simplebus, jz4780_gpio_driver,
  840     jz4780_gpio_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);

Cache object: c71d8ab060274f94b37b706702c31dc6


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