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/qcom_qup/qcom_spi.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2021, Adrian Chadd <adrian@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice unmodified, this list of conditions, and the following
   11  *    disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 
   35 #include <sys/bus.h>
   36 #include <sys/interrupt.h>
   37 #include <sys/malloc.h>
   38 #include <sys/lock.h>
   39 #include <sys/mutex.h>
   40 #include <sys/kernel.h>
   41 #include <sys/module.h>
   42 #include <sys/rman.h>
   43 #include <sys/gpio.h>
   44 
   45 #include <vm/vm.h>
   46 #include <vm/pmap.h>
   47 #include <vm/vm_extern.h>
   48 
   49 #include <machine/bus.h>
   50 #include <machine/cpu.h>
   51 
   52 #include <dev/fdt/fdt_common.h>
   53 #include <dev/fdt/fdt_pinctrl.h>
   54 
   55 #include <dev/gpio/gpiobusvar.h>
   56 #include <dev/ofw/ofw_bus.h>
   57 #include <dev/ofw/ofw_bus_subr.h>
   58 
   59 #include <dev/extres/clk/clk.h>
   60 #include <dev/extres/hwreset/hwreset.h>
   61 
   62 #include <dev/spibus/spi.h>
   63 #include <dev/spibus/spibusvar.h>
   64 #include "spibus_if.h"
   65 
   66 #include <dev/qcom_qup/qcom_spi_var.h>
   67 #include <dev/qcom_qup/qcom_qup_reg.h>
   68 #include <dev/qcom_qup/qcom_spi_reg.h>
   69 #include <dev/qcom_qup/qcom_spi_debug.h>
   70 
   71 static struct ofw_compat_data compat_data[] = {
   72         { "qcom,spi-qup-v1.1.1",        QCOM_SPI_HW_QPI_V1_1 },
   73         { "qcom,spi-qup-v2.1.1",        QCOM_SPI_HW_QPI_V2_1 },
   74         { "qcom,spi-qup-v2.2.1",        QCOM_SPI_HW_QPI_V2_2 },
   75         { NULL,                         0 }
   76 };
   77 
   78 /*
   79  * Flip the CS GPIO line either active or inactive.
   80  *
   81  * Actually listen to the CS polarity.
   82  */
   83 static void
   84 qcom_spi_set_chipsel(struct qcom_spi_softc *sc, int cs, bool active)
   85 {
   86         bool pinactive;
   87         bool invert = !! (cs & SPIBUS_CS_HIGH);
   88 
   89         cs = cs & ~SPIBUS_CS_HIGH;
   90 
   91         if (sc->cs_pins[cs] == NULL) {
   92                 device_printf(sc->sc_dev,
   93                     "%s: cs=%u, active=%u, invert=%u, no gpio?\n",
   94                     __func__, cs, active, invert);
   95                 return;
   96         }
   97 
   98         QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_CHIPSELECT,
   99             "%s: cs=%u active=%u\n", __func__, cs, active);
  100 
  101         /*
  102          * Default rule here is CS is active low.
  103          */
  104         if (active)
  105                 pinactive = false;
  106         else
  107                 pinactive = true;
  108 
  109         /*
  110          * Invert the CS line if required.
  111          */
  112         if (invert)
  113                 pinactive = !! pinactive;
  114 
  115         gpio_pin_set_active(sc->cs_pins[cs], pinactive);
  116         gpio_pin_is_active(sc->cs_pins[cs], &pinactive);
  117 }
  118 
  119 static void
  120 qcom_spi_intr(void *arg)
  121 {
  122         struct qcom_spi_softc *sc = arg;
  123         int ret;
  124 
  125         QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_INTR, "%s: called\n", __func__);
  126 
  127 
  128         QCOM_SPI_LOCK(sc);
  129         ret = qcom_spi_hw_interrupt_handle(sc);
  130         if (ret != 0) {
  131                 device_printf(sc->sc_dev,
  132                     "ERROR: failed to read intr status\n");
  133                 goto done;
  134         }
  135 
  136         /*
  137          * Handle spurious interrupts outside of an actual
  138          * transfer.
  139          */
  140         if (sc->transfer.active == false) {
  141                 device_printf(sc->sc_dev,
  142                     "ERROR: spurious interrupt\n");
  143                 qcom_spi_hw_ack_opmode(sc);
  144                 goto done;
  145         }
  146 
  147         /* Now, handle interrupts */
  148         if (sc->intr.error) {
  149                 sc->intr.error = false;
  150                 device_printf(sc->sc_dev, "ERROR: intr\n");
  151         }
  152 
  153         if (sc->intr.do_rx) {
  154                 sc->intr.do_rx = false;
  155                 QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_INTR,
  156                     "%s: PIO_READ\n", __func__);
  157                 if (sc->state.transfer_mode == QUP_IO_M_MODE_FIFO)
  158                         ret = qcom_spi_hw_read_pio_fifo(sc);
  159                 else
  160                         ret = qcom_spi_hw_read_pio_block(sc);
  161                 if (ret != 0) {
  162                         device_printf(sc->sc_dev,
  163                             "ERROR: qcom_spi_hw_read failed (%u)\n", ret);
  164                         goto done;
  165                 }
  166         }
  167         if (sc->intr.do_tx) {
  168                 sc->intr.do_tx = false;
  169                 QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_INTR,
  170                     "%s: PIO_WRITE\n", __func__);
  171                 /*
  172                  * For FIFO operations we do not do a write here, we did
  173                  * it at the beginning of the transfer.
  174                  *
  175                  * For BLOCK operations yes, we call the routine.
  176                  */
  177 
  178                 if (sc->state.transfer_mode == QUP_IO_M_MODE_FIFO)
  179                         ret = qcom_spi_hw_ack_write_pio_fifo(sc);
  180                 else
  181                         ret = qcom_spi_hw_write_pio_block(sc);
  182                 if (ret != 0) {
  183                         device_printf(sc->sc_dev,
  184                             "ERROR: qcom_spi_hw_write failed (%u)\n", ret);
  185                         goto done;
  186                 }
  187         }
  188 
  189         /*
  190          * Do this last.  We may actually have completed the
  191          * transfer in the PIO receive path above and it will
  192          * set the done flag here.
  193          */
  194         if (sc->intr.done) {
  195                 sc->intr.done = false;
  196                 sc->transfer.done = true;
  197                 QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_INTR,
  198                     "%s: transfer done\n", __func__);
  199                 wakeup(sc);
  200         }
  201 
  202 done:
  203         QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_INTR,
  204             "%s: done\n", __func__);
  205         QCOM_SPI_UNLOCK(sc);
  206 }
  207 
  208 static int
  209 qcom_spi_probe(device_t dev)
  210 {
  211 
  212         if (!ofw_bus_status_okay(dev))
  213                 return (ENXIO);
  214 
  215         if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
  216                 return (ENXIO);
  217 
  218         device_set_desc(dev, "Qualcomm SPI Interface");
  219         return (BUS_PROBE_DEFAULT);
  220 }
  221 
  222 /*
  223  * Allocate GPIOs if provided in the SPI controller block.
  224  *
  225  * Some devices will use GPIO lines for chip select.
  226  * It's also quite annoying because some devices will want to use
  227  * the hardware provided CS gating for say, the first chipselect block,
  228  * and then use GPIOs for the later ones.
  229  *
  230  * So here we just assume for now that SPI index 0 uses the hardware
  231  * lines, and >0 use GPIO lines.  Revisit this if better hardware
  232  * shows up.
  233  *
  234  * And finally, iterating over the cs-gpios list to allocate GPIOs
  235  * doesn't actually tell us what the polarity is.  For that we need
  236  * to actually iterate over the list of child nodes and check what
  237  * their properties are (and look for "spi-cs-high".)
  238  */
  239 static void
  240 qcom_spi_attach_gpios(struct qcom_spi_softc *sc)
  241 {
  242         phandle_t node;
  243         int idx, err;
  244 
  245         /* Allocate gpio pins for configured chip selects. */
  246         node = ofw_bus_get_node(sc->sc_dev);
  247         for (idx = 0; idx < nitems(sc->cs_pins); idx++) {
  248                 err = gpio_pin_get_by_ofw_propidx(sc->sc_dev, node,
  249                     "cs-gpios", idx, &sc->cs_pins[idx]);
  250                 if (err == 0) {
  251                         err = gpio_pin_setflags(sc->cs_pins[idx],
  252                             GPIO_PIN_OUTPUT);
  253                         if (err != 0) {
  254                                 device_printf(sc->sc_dev,
  255                                     "error configuring gpio for"
  256                                     " cs %u (%d)\n", idx, err);
  257                         }
  258                         /*
  259                          * We can't set this HIGH right now because
  260                          * we don't know if it needs to be set to
  261                          * high for inactive or low for inactive
  262                          * based on the child SPI device flags.
  263                          */
  264 #if 0
  265                         gpio_pin_set_active(sc->cs_pins[idx], 1);
  266                         gpio_pin_is_active(sc->cs_pins[idx], &tmp);
  267 #endif
  268                 } else {
  269                         device_printf(sc->sc_dev,
  270                             "cannot configure gpio for chip select %u\n", idx);
  271                         sc->cs_pins[idx] = NULL;
  272                 }
  273         }
  274 }
  275 
  276 static void
  277 qcom_spi_sysctl_attach(struct qcom_spi_softc *sc)
  278 {
  279         struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
  280         struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
  281 
  282         SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
  283             "debug", CTLFLAG_RW, &sc->sc_debug, 0,
  284             "control debugging printfs");
  285 }
  286 
  287 static int
  288 qcom_spi_attach(device_t dev)
  289 {
  290         struct qcom_spi_softc *sc = device_get_softc(dev);
  291         int rid, ret, i, val;
  292 
  293         sc->sc_dev = dev;
  294 
  295         /*
  296          * Hardware version is stored in the ofw_compat_data table.
  297          */
  298         sc->hw_version =
  299             ofw_bus_search_compatible(dev, compat_data)->ocd_data;
  300 
  301         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  302 
  303         rid = 0;
  304         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  305             RF_ACTIVE);
  306         if (!sc->sc_mem_res) {
  307                 device_printf(dev, "ERROR: Could not map memory\n");
  308                 ret = ENXIO;
  309                 goto error;
  310         }
  311 
  312         rid = 0;
  313         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  314             RF_ACTIVE | RF_SHAREABLE);
  315         if (!sc->sc_irq_res) {
  316                 device_printf(dev, "ERROR: Could not map interrupt\n");
  317                 ret = ENXIO;
  318                 goto error;
  319         }
  320 
  321         ret = bus_setup_intr(dev, sc->sc_irq_res,
  322             INTR_TYPE_MISC | INTR_MPSAFE,
  323             NULL, qcom_spi_intr, sc, &sc->sc_irq_h);
  324         if (ret != 0) {
  325                 device_printf(dev, "ERROR: could not configure interrupt "
  326                     "(%d)\n",
  327                     ret);
  328                 goto error;
  329         }
  330 
  331         qcom_spi_attach_gpios(sc);
  332 
  333         ret = clk_get_by_ofw_name(dev, 0, "core", &sc->clk_core);
  334         if (ret != 0) {
  335                 device_printf(dev, "ERROR: could not get %s clock (%d)\n",
  336                     "core", ret);
  337                 goto error;
  338         }
  339         ret = clk_get_by_ofw_name(dev, 0, "iface", &sc->clk_iface);
  340         if (ret != 0) {
  341                 device_printf(dev, "ERROR: could not get %s clock (%d)\n",
  342                     "iface", ret);
  343                 goto error;
  344         }
  345 
  346         /* Bring up initial clocks if they're off */
  347         ret = clk_enable(sc->clk_core);
  348         if (ret != 0) {
  349                 device_printf(dev, "ERROR: couldn't enable core clock (%u)\n",
  350                     ret);
  351                 goto error;
  352         }
  353         ret = clk_enable(sc->clk_iface);
  354         if (ret != 0) {
  355                 device_printf(dev, "ERROR: couldn't enable iface clock (%u)\n",
  356                     ret);
  357                 goto error;
  358         }
  359 
  360         /*
  361          * Read optional spi-max-frequency
  362          */
  363         if (OF_getencprop(ofw_bus_get_node(dev), "spi-max-frequency",
  364             &val, sizeof(val)) > 0)
  365                 sc->config.max_frequency = val;
  366         else
  367                 sc->config.max_frequency = SPI_MAX_RATE;
  368 
  369         /*
  370          * Read optional cs-select
  371          */
  372         if (OF_getencprop(ofw_bus_get_node(dev), "cs-select",
  373             &val, sizeof(val)) > 0)
  374                 sc->config.cs_select = val;
  375         else
  376                 sc->config.cs_select = 0;
  377 
  378         /*
  379          * Read optional num-cs
  380          */
  381         if (OF_getencprop(ofw_bus_get_node(dev), "num-cs",
  382             &val, sizeof(val)) > 0)
  383                 sc->config.num_cs = val;
  384         else
  385                 sc->config.num_cs = SPI_NUM_CHIPSELECTS;
  386 
  387         ret = fdt_pinctrl_configure_by_name(dev, "default");
  388         if (ret != 0) {
  389                 device_printf(dev,
  390                     "ERROR: could not configure default pinmux\n");
  391                 goto error;
  392         }
  393 
  394         ret = qcom_spi_hw_read_controller_transfer_sizes(sc);
  395         if (ret != 0) {
  396                 device_printf(dev, "ERROR: Could not read transfer config\n");
  397                 goto error;
  398         }
  399 
  400 
  401         device_printf(dev, "BLOCK: input=%u bytes, output=%u bytes\n",
  402             sc->config.input_block_size,
  403             sc->config.output_block_size);
  404         device_printf(dev, "FIFO: input=%u bytes, output=%u bytes\n",
  405             sc->config.input_fifo_size,
  406             sc->config.output_fifo_size);
  407 
  408         /* QUP config */
  409         QCOM_SPI_LOCK(sc);
  410         ret = qcom_spi_hw_qup_init_locked(sc);
  411         if (ret != 0) {
  412                 device_printf(dev, "ERROR: QUP init failed (%d)\n", ret);
  413                 QCOM_SPI_UNLOCK(sc);
  414                 goto error;
  415         }
  416 
  417         /* Initial SPI config */
  418         ret = qcom_spi_hw_spi_init_locked(sc);
  419         if (ret != 0) {
  420                 device_printf(dev, "ERROR: SPI init failed (%d)\n", ret);
  421                 QCOM_SPI_UNLOCK(sc);
  422                 goto error;
  423         }
  424         QCOM_SPI_UNLOCK(sc);
  425 
  426         sc->spibus = device_add_child(dev, "spibus", -1);
  427 
  428         /* We're done, so shut down the interface clock for now */
  429         device_printf(dev, "DONE: shutting down interface clock for now\n");
  430         clk_disable(sc->clk_iface);
  431 
  432         /* Register for debug sysctl */
  433         qcom_spi_sysctl_attach(sc);
  434 
  435         return (bus_generic_attach(dev));
  436 error:
  437         if (sc->sc_irq_h)
  438                 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_h);
  439         if (sc->sc_mem_res)
  440                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
  441         if (sc->sc_irq_res)
  442                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
  443         if (sc->clk_core) {
  444                 clk_disable(sc->clk_core);
  445                 clk_release(sc->clk_core);
  446         }
  447         if (sc->clk_iface) {
  448                 clk_disable(sc->clk_iface);
  449                 clk_release(sc->clk_iface);
  450         }
  451         for (i = 0; i < CS_MAX; i++) {
  452                 if (sc->cs_pins[i] != NULL)
  453                         gpio_pin_release(sc->cs_pins[i]);
  454         }
  455         mtx_destroy(&sc->sc_mtx);
  456         return (ret);
  457 }
  458 
  459 /*
  460  * Do a PIO transfer.
  461  *
  462  * Note that right now the TX/RX lens need to match, I'm not doing
  463  * dummy reads / dummy writes as required if they're not the same
  464  * size.  The QUP hardware supports doing multi-phase transactions
  465  * where the FIFO isn't engaged for transmit or receive, but it's
  466  * not yet being done here.
  467  */
  468 static int
  469 qcom_spi_transfer_pio_block(struct qcom_spi_softc *sc, int mode,
  470     char *tx_buf, int tx_len, char *rx_buf, int rx_len)
  471 {
  472         int ret = 0;
  473 
  474         QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_TRANSFER, "%s: start\n",
  475             __func__);
  476 
  477         if (rx_len != tx_len) {
  478                 device_printf(sc->sc_dev,
  479                     "ERROR: tx/rx len doesn't match (%d/%d)\n",
  480                     tx_len, rx_len);
  481                 return (ENXIO);
  482         }
  483 
  484         QCOM_SPI_ASSERT_LOCKED(sc);
  485 
  486         /*
  487          * Make initial choices for transfer configuration.
  488          */
  489         ret = qcom_spi_hw_setup_transfer_selection(sc, tx_len);
  490         if (ret != 0) {
  491                 device_printf(sc->sc_dev,
  492                     "ERROR: failed to setup transfer selection (%d)\n",
  493                     ret);
  494                 return (ret);
  495         }
  496 
  497         /* Now set suitable buffer/lengths */
  498         sc->transfer.tx_buf = tx_buf;
  499         sc->transfer.tx_len = tx_len;
  500         sc->transfer.rx_buf = rx_buf;
  501         sc->transfer.rx_len = rx_len;
  502         sc->transfer.done = false;
  503         sc->transfer.active = false;
  504 
  505         /*
  506          * Loop until the full transfer set is done.
  507          *
  508          * qcom_spi_hw_setup_current_transfer() will take care of
  509          * setting a maximum transfer size for the hardware and choose
  510          * a suitable operating mode.
  511          */
  512         while (sc->transfer.tx_offset < sc->transfer.tx_len) {
  513                 /*
  514                  * Set transfer to false early; this covers
  515                  * it also finishing a sub-transfer and we're
  516                  * about the put the block into RESET state before
  517                  * starting a new transfer.
  518                  */
  519                 sc->transfer.active = false;
  520 
  521                 QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_TRANSFER,
  522                     "%s: tx=%d of %d bytes, rx=%d of %d bytes\n",
  523                     __func__,
  524                     sc->transfer.tx_offset, sc->transfer.tx_len,
  525                     sc->transfer.rx_offset, sc->transfer.rx_len);
  526 
  527                 /*
  528                  * Set state to RESET before doing anything.
  529                  *
  530                  * Otherwise the second sub-transfer that we queue up
  531                  * will generate interrupts immediately when we start
  532                  * configuring it here and it'll start underflowing.
  533                  */
  534                 ret = qcom_spi_hw_qup_set_state_locked(sc, QUP_STATE_RESET);
  535                 if (ret != 0) {
  536                         device_printf(sc->sc_dev,
  537                             "ERROR: can't transition to RESET (%u)\n", ret);
  538                         goto done;
  539                 }
  540                 /* blank interrupt state; we'll do a RESET below */
  541                 bzero(&sc->intr, sizeof(sc->intr));
  542                 sc->transfer.done = false;
  543 
  544                 /*
  545                  * Configure what the transfer configuration for this
  546                  * sub-transfer will be.
  547                  */
  548                 ret = qcom_spi_hw_setup_current_transfer(sc);
  549                 if (ret != 0) {
  550                         device_printf(sc->sc_dev,
  551                             "ERROR: failed to setup sub transfer (%d)\n",
  552                             ret);
  553                         goto done;
  554                 }
  555 
  556                 /*
  557                  * For now since we're configuring up PIO, we only setup
  558                  * the PIO transfer size.
  559                  */
  560                 ret = qcom_spi_hw_setup_pio_transfer_cnt(sc);
  561                 if (ret != 0) {
  562                         device_printf(sc->sc_dev,
  563                             "ERROR: qcom_spi_hw_setup_pio_transfer_cnt failed"
  564                             " (%u)\n", ret);
  565                         goto done;
  566                 }
  567 
  568 #if 0
  569                 /*
  570                  * This is what we'd do to setup the block transfer sizes.
  571                  */
  572                 ret = qcom_spi_hw_setup_block_transfer_cnt(sc);
  573                 if (ret != 0) {
  574                         device_printf(sc->sc_dev,
  575                             "ERROR: qcom_spi_hw_setup_block_transfer_cnt failed"
  576                             " (%u)\n", ret);
  577                         goto done;
  578                 }
  579 #endif
  580 
  581                 ret = qcom_spi_hw_setup_io_modes(sc);
  582                 if (ret != 0) {
  583                         device_printf(sc->sc_dev,
  584                             "ERROR: qcom_spi_hw_setup_io_modes failed"
  585                             " (%u)\n", ret);
  586                         goto done;
  587                 }
  588 
  589                 ret = qcom_spi_hw_setup_spi_io_clock_polarity(sc,
  590                     !! (mode & SPIBUS_MODE_CPOL));
  591                 if (ret != 0) {
  592                         device_printf(sc->sc_dev,
  593                             "ERROR: qcom_spi_hw_setup_spi_io_clock_polarity"
  594                             "    failed (%u)\n", ret);
  595                         goto done;
  596                 }
  597 
  598                 ret = qcom_spi_hw_setup_spi_config(sc, sc->state.frequency,
  599                     !! (mode & SPIBUS_MODE_CPHA));
  600                 if (ret != 0) {
  601                         device_printf(sc->sc_dev,
  602                             "ERROR: qcom_spi_hw_setup_spi_config failed"
  603                             " (%u)\n", ret);
  604                         goto done;
  605                 }
  606 
  607                 ret = qcom_spi_hw_setup_qup_config(sc, !! (tx_len > 0),
  608                     !! (rx_len > 0));
  609                 if (ret != 0) {
  610                         device_printf(sc->sc_dev,
  611                             "ERROR: qcom_spi_hw_setup_qup_config failed"
  612                             " (%u)\n", ret);
  613                         goto done;
  614                 }
  615 
  616                 ret = qcom_spi_hw_setup_operational_mask(sc);
  617                 if (ret != 0) {
  618                         device_printf(sc->sc_dev,
  619                             "ERROR: qcom_spi_hw_setup_operational_mask failed"
  620                             " (%u)\n", ret);
  621                         goto done;
  622                 }
  623 
  624                 /*
  625                  * Setup is done; reset the controller and start the PIO
  626                  * write.
  627                  */
  628 
  629                 /*
  630                  * Set state to RUN; we may start getting interrupts that
  631                  * are valid and we need to handle.
  632                  */
  633                 sc->transfer.active = true;
  634                 ret = qcom_spi_hw_qup_set_state_locked(sc, QUP_STATE_RUN);
  635                 if (ret != 0) {
  636                         device_printf(sc->sc_dev,
  637                             "ERROR: can't transition to RUN (%u)\n", ret);
  638                         goto done;
  639                 }
  640 
  641                 /*
  642                  * Set state to PAUSE
  643                  */
  644                 ret = qcom_spi_hw_qup_set_state_locked(sc, QUP_STATE_PAUSE);
  645                 if (ret != 0) {
  646                         device_printf(sc->sc_dev,
  647                             "ERROR: can't transition to PAUSE (%u)\n", ret);
  648                         goto done;
  649                 }
  650 
  651                 /*
  652                  * If FIFO mode, write data now.  Else, we'll get an
  653                  * interrupt when it's time to populate more data
  654                  * in BLOCK mode.
  655                  */
  656                 if (sc->state.transfer_mode == QUP_IO_M_MODE_FIFO)
  657                         ret = qcom_spi_hw_write_pio_fifo(sc);
  658                 else
  659                         ret = qcom_spi_hw_write_pio_block(sc);
  660                 if (ret != 0) {
  661                         device_printf(sc->sc_dev,
  662                             "ERROR: qcom_spi_hw_write failed (%u)\n", ret);
  663                         goto done;
  664                 }
  665 
  666                 /*
  667                  * Set state to RUN
  668                  */
  669                 ret = qcom_spi_hw_qup_set_state_locked(sc, QUP_STATE_RUN);
  670                 if (ret != 0) {
  671                         device_printf(sc->sc_dev,
  672                             "ERROR: can't transition to RUN (%u)\n", ret);
  673                         goto done;
  674                 }
  675 
  676                 /*
  677                  * Wait for an interrupt notification (which will
  678                  * continue to drive the state machine for this
  679                  * sub-transfer) or timeout.
  680                  */
  681                 ret = 0;
  682                 while (ret == 0 && sc->transfer.done == false) {
  683                         QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_TRANSFER,
  684                             "%s: waiting\n", __func__);
  685                         ret = msleep(sc, &sc->sc_mtx, 0, "qcom_spi", 0);
  686                 }
  687         }
  688 done:
  689         /*
  690          * Complete; put controller into reset.
  691          *
  692          * Don't worry about return value here; if we errored out above then
  693          * we want to communicate that value to the caller.
  694          */
  695         (void) qcom_spi_hw_qup_set_state_locked(sc, QUP_STATE_RESET);
  696         QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_TRANSFER,
  697             "%s: completed\n", __func__);
  698 
  699          /*
  700           * Blank the transfer state so we don't use an old transfer
  701           * state in a subsequent interrupt.
  702           */
  703         (void) qcom_spi_hw_complete_transfer(sc);
  704         sc->transfer.active = false;
  705 
  706         return (ret);
  707 }
  708 
  709 static int
  710 qcom_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
  711 {
  712         struct qcom_spi_softc *sc = device_get_softc(dev);
  713         uint32_t cs_val, mode_val, clock_val;
  714         uint32_t ret = 0;
  715 
  716         spibus_get_cs(child, &cs_val);
  717         spibus_get_clock(child, &clock_val);
  718         spibus_get_mode(child, &mode_val);
  719 
  720         QCOM_SPI_DPRINTF(sc, QCOM_SPI_DEBUG_TRANSFER,
  721             "%s: called; child cs=0x%08x, clock=%u, mode=0x%08x, "
  722             "cmd=%u/%u bytes; data=%u/%u bytes\n",
  723             __func__,
  724             cs_val,
  725             clock_val,
  726             mode_val,
  727             cmd->tx_cmd_sz, cmd->rx_cmd_sz,
  728             cmd->tx_data_sz, cmd->rx_data_sz);
  729 
  730         QCOM_SPI_LOCK(sc);
  731 
  732         /*
  733          * wait until the controller isn't busy
  734          */
  735         while (sc->sc_busy == true)
  736                 mtx_sleep(sc, &sc->sc_mtx, 0, "qcom_spi_wait", 0);
  737 
  738         /*
  739          * it's ours now!
  740          */
  741         sc->sc_busy = true;
  742 
  743         sc->state.cs_high = !! (cs_val & SPIBUS_CS_HIGH);
  744         sc->state.frequency = clock_val;
  745 
  746         /*
  747          * We can't set the clock frequency and enable it
  748          * with the driver lock held, as the SPI lock is non-sleepable
  749          * and the clock framework is sleepable.
  750          *
  751          * No other transaction is going on right now, so we can
  752          * unlock here and do the clock related work.
  753          */
  754         QCOM_SPI_UNLOCK(sc);
  755 
  756         /*
  757          * Set the clock frequency
  758          */
  759         ret = clk_set_freq(sc->clk_iface, sc->state.frequency, 0);
  760         if (ret != 0) {
  761                 device_printf(sc->sc_dev,
  762                     "ERROR: failed to set frequency to %u\n",
  763                     sc->state.frequency);
  764                 goto done2;
  765         }
  766         clk_enable(sc->clk_iface);
  767 
  768         QCOM_SPI_LOCK(sc);
  769 
  770         /*
  771          * Set state to RESET
  772          */
  773         ret = qcom_spi_hw_qup_set_state_locked(sc, QUP_STATE_RESET);
  774         if (ret != 0) {
  775                 device_printf(sc->sc_dev,
  776                     "ERROR: can't transition to RESET (%u)\n", ret);
  777                 goto done;
  778         }
  779 
  780         /* Assert hardware CS if set, else GPIO */
  781         if (sc->cs_pins[cs_val & ~SPIBUS_CS_HIGH] == NULL)
  782                 qcom_spi_hw_spi_cs_force(sc, cs_val & SPIBUS_CS_HIGH, true);
  783         else
  784                 qcom_spi_set_chipsel(sc, cs_val & ~SPIBUS_CS_HIGH, true);
  785 
  786         /*
  787          * cmd buffer transfer
  788          */
  789         ret = qcom_spi_transfer_pio_block(sc, mode_val, cmd->tx_cmd,
  790             cmd->tx_cmd_sz, cmd->rx_cmd, cmd->rx_cmd_sz);
  791         if (ret != 0) {
  792                 device_printf(sc->sc_dev,
  793                     "ERROR: failed to transfer cmd payload (%u)\n", ret);
  794                 goto done;
  795         }
  796 
  797         /*
  798          * data buffer transfer
  799          */
  800         if (cmd->tx_data_sz > 0) {
  801                 ret = qcom_spi_transfer_pio_block(sc, mode_val, cmd->tx_data,
  802                     cmd->tx_data_sz, cmd->rx_data, cmd->rx_data_sz);
  803                 if (ret != 0) {
  804                         device_printf(sc->sc_dev,
  805                             "ERROR: failed to transfer data payload (%u)\n",
  806                             ret);
  807                         goto done;
  808                 }
  809         }
  810 
  811 done:
  812         /* De-assert GPIO/CS */
  813         if (sc->cs_pins[cs_val & ~SPIBUS_CS_HIGH] == NULL)
  814                 qcom_spi_hw_spi_cs_force(sc, cs_val & ~SPIBUS_CS_HIGH, false);
  815         else
  816                 qcom_spi_set_chipsel(sc, cs_val & ~SPIBUS_CS_HIGH, false);
  817 
  818         /*
  819          * Similarly to when we enabled the clock, we can't hold it here
  820          * across a clk API as that's a sleep lock and we're non-sleepable.
  821          * So instead we unlock/relock here, but we still hold the busy flag.
  822          */
  823 
  824         QCOM_SPI_UNLOCK(sc);
  825         clk_disable(sc->clk_iface);
  826         QCOM_SPI_LOCK(sc);
  827 done2:
  828         /*
  829          * We're done; so mark the bus as not busy and wakeup
  830          * the next caller.
  831          */
  832         sc->sc_busy = false;
  833         wakeup_one(sc);
  834         QCOM_SPI_UNLOCK(sc);
  835         return (ret);
  836 }
  837 
  838 static int
  839 qcom_spi_detach(device_t dev)
  840 {
  841         struct qcom_spi_softc *sc = device_get_softc(dev);
  842         int i;
  843 
  844         bus_generic_detach(sc->sc_dev);
  845         if (sc->spibus != NULL)
  846                 device_delete_child(dev, sc->spibus);
  847 
  848         if (sc->sc_irq_h)
  849                 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_h);
  850 
  851         if (sc->clk_iface) {
  852                 clk_disable(sc->clk_iface);
  853                 clk_release(sc->clk_iface);
  854         }
  855         if (sc->clk_core) {
  856                 clk_disable(sc->clk_core);
  857                 clk_release(sc->clk_core);
  858         }
  859 
  860         for (i = 0; i < CS_MAX; i++) {
  861                 if (sc->cs_pins[i] != NULL)
  862                         gpio_pin_release(sc->cs_pins[i]);
  863         }
  864 
  865         if (sc->sc_mem_res)
  866                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
  867         if (sc->sc_irq_res)
  868                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
  869 
  870         mtx_destroy(&sc->sc_mtx);
  871 
  872         return (0);
  873 }
  874 
  875 static phandle_t
  876 qcom_spi_get_node(device_t bus, device_t dev)
  877 {
  878 
  879         return ofw_bus_get_node(bus);
  880 }
  881 
  882 
  883 static device_method_t qcom_spi_methods[] = {
  884         /* Device interface */
  885         DEVMETHOD(device_probe,         qcom_spi_probe),
  886         DEVMETHOD(device_attach,        qcom_spi_attach),
  887         DEVMETHOD(device_detach,        qcom_spi_detach),
  888         /* TODO: suspend */
  889         /* TODO: resume */
  890 
  891         DEVMETHOD(spibus_transfer,      qcom_spi_transfer),
  892 
  893         /* ofw_bus_if */
  894         DEVMETHOD(ofw_bus_get_node,     qcom_spi_get_node),
  895 
  896         DEVMETHOD_END
  897 };
  898 
  899 static driver_t qcom_spi_driver = {
  900         "qcom_spi",
  901         qcom_spi_methods,
  902         sizeof(struct qcom_spi_softc),
  903 };
  904 
  905 DRIVER_MODULE(qcom_spi, simplebus, qcom_spi_driver, 0, 0);
  906 DRIVER_MODULE(ofw_spibus, qcom_spi, ofw_spibus_driver, 0, 0);
  907 MODULE_DEPEND(qcom_spi, ofw_spibus, 1, 1, 1);
  908 SIMPLEBUS_PNP_INFO(compat_data);

Cache object: 1864a6ff66b5a033741868521f89535b


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