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


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

FreeBSD/Linux Kernel Cross Reference
sys/arm/ti/ti_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  * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  */
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 
   34 #include <sys/kernel.h>
   35 #include <sys/module.h>
   36 #include <sys/rman.h>
   37 #include <sys/lock.h>
   38 #include <sys/mutex.h>
   39 #include <sys/sysctl.h>
   40 
   41 #include <machine/bus.h>
   42 #include <machine/resource.h>
   43 #include <machine/intr.h>
   44 
   45 #include <dev/ofw/ofw_bus.h>
   46 #include <dev/ofw/ofw_bus_subr.h>
   47 
   48 #include <dev/spibus/spi.h>
   49 #include <dev/spibus/spibusvar.h>
   50 
   51 #include <arm/ti/ti_sysc.h>
   52 #include <arm/ti/ti_spireg.h>
   53 #include <arm/ti/ti_spivar.h>
   54 
   55 #include "spibus_if.h"
   56 
   57 static void ti_spi_intr(void *);
   58 static int ti_spi_detach(device_t);
   59 
   60 #undef TI_SPI_DEBUG
   61 #ifdef TI_SPI_DEBUG
   62 #define IRQSTATUSBITS                                                   \
   63         "\020\1TX0_EMPTY\2TX0_UNDERFLOW\3RX0_FULL\4RX0_OVERFLOW"        \
   64         "\5TX1_EMPTY\6TX1_UNDERFLOW\7RX1_FULL\11TX2_EMPTY"              \
   65         "\12TX1_UNDERFLOW\13RX2_FULL\15TX3_EMPTY\16TX3_UNDERFLOW"       \
   66         "\17RX3_FULL\22EOW"
   67 #define CONFBITS                                                        \
   68         "\020\1PHA\2POL\7EPOL\17DMAW\20DMAR\21DPE0\22DPE1\23IS"         \
   69         "\24TURBO\25FORCE\30SBE\31SBPOL\34FFEW\35FFER\36CLKG"
   70 #define STATBITS                                                        \
   71         "\020\1RXS\2TXS\3EOT\4TXFFE\5TXFFF\6RXFFE\7RXFFFF"
   72 #define MODULCTRLBITS                                                   \
   73         "\020\1SINGLE\2NOSPIEN\3SLAVE\4SYST\10MOA\11FDAA"
   74 #define CTRLBITS                                                        \
   75         "\020\1ENABLED"
   76 
   77 static void
   78 ti_spi_printr(device_t dev)
   79 {
   80         int clk, conf, ctrl, div, i, j, wl;
   81         struct ti_spi_softc *sc;
   82         uint32_t reg;
   83 
   84         sc = device_get_softc(dev);
   85         reg = TI_SPI_READ(sc, MCSPI_SYSCONFIG);
   86         device_printf(dev, "SYSCONFIG: %#x\n", reg);
   87         reg = TI_SPI_READ(sc, MCSPI_SYSSTATUS);
   88         device_printf(dev, "SYSSTATUS: %#x\n", reg);
   89         reg = TI_SPI_READ(sc, MCSPI_IRQSTATUS);
   90         device_printf(dev, "IRQSTATUS: 0x%b\n", reg, IRQSTATUSBITS);
   91         reg = TI_SPI_READ(sc, MCSPI_IRQENABLE);
   92         device_printf(dev, "IRQENABLE: 0x%b\n", reg, IRQSTATUSBITS);
   93         reg = TI_SPI_READ(sc, MCSPI_MODULCTRL);
   94         device_printf(dev, "MODULCTRL: 0x%b\n", reg, MODULCTRLBITS);
   95         for (i = 0; i < sc->sc_numcs; i++) {
   96                 ctrl = TI_SPI_READ(sc, MCSPI_CTRL_CH(i));
   97                 conf = TI_SPI_READ(sc, MCSPI_CONF_CH(i));
   98                 device_printf(dev, "CH%dCONF: 0x%b\n", i, conf, CONFBITS);
   99                 if (conf & MCSPI_CONF_CLKG) {
  100                         div = (conf >> MCSPI_CONF_CLK_SHIFT) & MCSPI_CONF_CLK_MSK;
  101                         div |= ((ctrl >> MCSPI_CTRL_EXTCLK_SHIFT) & MCSPI_CTRL_EXTCLK_MSK) << 4;
  102                 } else {
  103                         div = 1;
  104                         j = (conf >> MCSPI_CONF_CLK_SHIFT) & MCSPI_CONF_CLK_MSK;
  105                         while (j-- > 0)
  106                                 div <<= 1;
  107                 }
  108                 clk = TI_SPI_GCLK / div;
  109                 wl = ((conf >> MCSPI_CONF_WL_SHIFT) & MCSPI_CONF_WL_MSK) + 1;
  110                 device_printf(dev, "wordlen: %-2d clock: %d\n", wl, clk);
  111                 reg = TI_SPI_READ(sc, MCSPI_STAT_CH(i));
  112                 device_printf(dev, "CH%dSTAT: 0x%b\n", i, reg, STATBITS);
  113                 device_printf(dev, "CH%dCTRL: 0x%b\n", i, ctrl, CTRLBITS);
  114         }
  115         reg = TI_SPI_READ(sc, MCSPI_XFERLEVEL);
  116         device_printf(dev, "XFERLEVEL: %#x\n", reg);
  117 }
  118 #endif
  119 
  120 static void
  121 ti_spi_set_clock(struct ti_spi_softc *sc, int ch, int freq)
  122 {
  123         uint32_t clkdiv, conf, div, extclk, reg;
  124 
  125         clkdiv = TI_SPI_GCLK / freq;
  126         if (clkdiv > MCSPI_EXTCLK_MSK) {
  127                 extclk = 0;
  128                 clkdiv = 0;
  129                 div = 1;
  130                 while (TI_SPI_GCLK / div > freq && clkdiv <= 0xf) {
  131                         clkdiv++;
  132                         div <<= 1;
  133                 }
  134                 conf = clkdiv << MCSPI_CONF_CLK_SHIFT;
  135         } else {
  136                 extclk = clkdiv >> 4;
  137                 clkdiv &= MCSPI_CONF_CLK_MSK;
  138                 conf = MCSPI_CONF_CLKG | clkdiv << MCSPI_CONF_CLK_SHIFT;
  139         }
  140 
  141         reg = TI_SPI_READ(sc, MCSPI_CTRL_CH(ch));
  142         reg &= ~(MCSPI_CTRL_EXTCLK_MSK << MCSPI_CTRL_EXTCLK_SHIFT);
  143         reg |= extclk << MCSPI_CTRL_EXTCLK_SHIFT;
  144         TI_SPI_WRITE(sc, MCSPI_CTRL_CH(ch), reg);
  145 
  146         reg = TI_SPI_READ(sc, MCSPI_CONF_CH(ch));
  147         reg &= ~(MCSPI_CONF_CLKG | MCSPI_CONF_CLK_MSK << MCSPI_CONF_CLK_SHIFT);
  148         TI_SPI_WRITE(sc, MCSPI_CONF_CH(ch), reg | conf);
  149 }
  150 
  151 static int
  152 ti_spi_probe(device_t dev)
  153 {
  154 
  155         if (!ofw_bus_status_okay(dev))
  156                 return (ENXIO);
  157         if (!ofw_bus_is_compatible(dev, "ti,omap4-mcspi"))
  158                 return (ENXIO);
  159 
  160         device_set_desc(dev, "TI McSPI controller");
  161 
  162         return (BUS_PROBE_DEFAULT);
  163 }
  164 
  165 static int
  166 ti_spi_attach(device_t dev)
  167 {
  168         int err, i, rid, timeout;
  169         struct ti_spi_softc *sc;
  170         uint32_t rev;
  171 
  172         sc = device_get_softc(dev);
  173         sc->sc_dev = dev;
  174 
  175         /* Activate the McSPI module. */
  176         err = ti_sysc_clock_enable(device_get_parent(dev));
  177         if (err) {
  178                 device_printf(dev, "Error: failed to activate source clock\n");
  179                 return (err);
  180         }
  181 
  182         /* Get the number of available channels. */
  183         if ((OF_getencprop(ofw_bus_get_node(dev), "ti,spi-num-cs",
  184             &sc->sc_numcs, sizeof(sc->sc_numcs))) <= 0) {
  185                 sc->sc_numcs = 2;
  186         }
  187 
  188         rid = 0;
  189         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  190             RF_ACTIVE);
  191         if (!sc->sc_mem_res) {
  192                 device_printf(dev, "cannot allocate memory window\n");
  193                 return (ENXIO);
  194         }
  195 
  196         sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
  197         sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
  198 
  199         rid = 0;
  200         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  201             RF_ACTIVE);
  202         if (!sc->sc_irq_res) {
  203                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
  204                 device_printf(dev, "cannot allocate interrupt\n");
  205                 return (ENXIO);
  206         }
  207 
  208         /* Hook up our interrupt handler. */
  209         if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
  210             NULL, ti_spi_intr, sc, &sc->sc_intrhand)) {
  211                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
  212                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
  213                 device_printf(dev, "cannot setup the interrupt handler\n");
  214                 return (ENXIO);
  215         }
  216 
  217         mtx_init(&sc->sc_mtx, "ti_spi", NULL, MTX_DEF);
  218 
  219         /* Issue a softreset to the controller */
  220         TI_SPI_WRITE(sc, MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET);
  221         timeout = 1000;
  222         while (!(TI_SPI_READ(sc, MCSPI_SYSSTATUS) &
  223             MCSPI_SYSSTATUS_RESETDONE)) {
  224                 if (--timeout == 0) {
  225                         device_printf(dev,
  226                             "Error: Controller reset operation timed out\n");
  227                         ti_spi_detach(dev);
  228                         return (ENXIO);
  229                 }
  230                 DELAY(100);
  231         }
  232 
  233         /* Print the McSPI module revision. */
  234         rev = TI_SPI_READ(sc,
  235             ti_sysc_get_rev_address_offset_host(device_get_parent(dev)));
  236         device_printf(dev,
  237             "scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n",
  238             (rev >> MCSPI_REVISION_SCHEME_SHIFT) & MCSPI_REVISION_SCHEME_MSK,
  239             (rev >> MCSPI_REVISION_FUNC_SHIFT) & MCSPI_REVISION_FUNC_MSK,
  240             (rev >> MCSPI_REVISION_RTL_SHIFT) & MCSPI_REVISION_RTL_MSK,
  241             (rev >> MCSPI_REVISION_MAJOR_SHIFT) & MCSPI_REVISION_MAJOR_MSK,
  242             (rev >> MCSPI_REVISION_MINOR_SHIFT) & MCSPI_REVISION_MINOR_MSK,
  243             (rev >> MCSPI_REVISION_CUSTOM_SHIFT) & MCSPI_REVISION_CUSTOM_MSK);
  244 
  245         /* Set Master mode, single channel. */
  246         TI_SPI_WRITE(sc, MCSPI_MODULCTRL, MCSPI_MODULCTRL_SINGLE);
  247 
  248         /* Clear pending interrupts and disable interrupts. */
  249         TI_SPI_WRITE(sc, MCSPI_IRQENABLE, 0x0);
  250         TI_SPI_WRITE(sc, MCSPI_IRQSTATUS, 0xffff);
  251 
  252         for (i = 0; i < sc->sc_numcs; i++) {
  253                 /*
  254                  * Default to SPI mode 0, CS active low, 8 bits word length and
  255                  * 500kHz clock.
  256                  */
  257                 TI_SPI_WRITE(sc, MCSPI_CONF_CH(i),
  258                     MCSPI_CONF_DPE0 | MCSPI_CONF_EPOL |
  259                     (8 - 1) << MCSPI_CONF_WL_SHIFT);
  260                 /* Set initial clock - 500kHz. */
  261                 ti_spi_set_clock(sc, i, 500000);
  262         }
  263 
  264 #ifdef  TI_SPI_DEBUG
  265         ti_spi_printr(dev);
  266 #endif
  267 
  268         device_add_child(dev, "spibus", -1);
  269 
  270         return (bus_generic_attach(dev));
  271 }
  272 
  273 static int
  274 ti_spi_detach(device_t dev)
  275 {
  276         struct ti_spi_softc *sc;
  277 
  278         sc = device_get_softc(dev);
  279 
  280         /* Clear pending interrupts and disable interrupts. */
  281         TI_SPI_WRITE(sc, MCSPI_IRQENABLE, 0);
  282         TI_SPI_WRITE(sc, MCSPI_IRQSTATUS, 0xffff);
  283 
  284         /* Reset controller. */
  285         TI_SPI_WRITE(sc, MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET);
  286 
  287         bus_generic_detach(dev);
  288 
  289         mtx_destroy(&sc->sc_mtx);
  290         if (sc->sc_intrhand)
  291                 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
  292         if (sc->sc_irq_res)
  293                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
  294         if (sc->sc_mem_res)
  295                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
  296 
  297         return (0);
  298 }
  299 
  300 static int
  301 ti_spi_fill_fifo(struct ti_spi_softc *sc)
  302 {
  303         int bytes, timeout;
  304         struct spi_command *cmd;
  305         uint32_t written;
  306         uint8_t *data;
  307 
  308         cmd = sc->sc_cmd;
  309         bytes = min(sc->sc_len - sc->sc_written, sc->sc_fifolvl);
  310         while (bytes-- > 0) {
  311                 data = (uint8_t *)cmd->tx_cmd;
  312                 written = sc->sc_written++;
  313                 if (written >= cmd->tx_cmd_sz) {
  314                         data = (uint8_t *)cmd->tx_data;
  315                         written -= cmd->tx_cmd_sz;
  316                 }
  317                 if (sc->sc_fifolvl == 1) {
  318                         /* FIFO disabled. */
  319                         timeout = 1000;
  320                         while (--timeout > 0 && (TI_SPI_READ(sc,
  321                             MCSPI_STAT_CH(sc->sc_cs)) & MCSPI_STAT_TXS) == 0) {
  322                                 DELAY(100);
  323                         }
  324                         if (timeout == 0)
  325                                 return (-1);
  326                 }
  327                 TI_SPI_WRITE(sc, MCSPI_TX_CH(sc->sc_cs), data[written]);
  328         }
  329 
  330         return (0);
  331 }
  332 
  333 static int
  334 ti_spi_drain_fifo(struct ti_spi_softc *sc)
  335 {
  336         int bytes, timeout;
  337         struct spi_command *cmd;
  338         uint32_t read;
  339         uint8_t *data;
  340 
  341         cmd = sc->sc_cmd;
  342         bytes = min(sc->sc_len - sc->sc_read, sc->sc_fifolvl);
  343         while (bytes-- > 0) {
  344                 data = (uint8_t *)cmd->rx_cmd;
  345                 read = sc->sc_read++;
  346                 if (read >= cmd->rx_cmd_sz) {
  347                         data = (uint8_t *)cmd->rx_data;
  348                         read -= cmd->rx_cmd_sz;
  349                 }
  350                 if (sc->sc_fifolvl == 1) {
  351                         /* FIFO disabled. */
  352                         timeout = 1000;
  353                         while (--timeout > 0 && (TI_SPI_READ(sc,
  354                             MCSPI_STAT_CH(sc->sc_cs)) & MCSPI_STAT_RXS) == 0) {
  355                                 DELAY(100);
  356                         }
  357                         if (timeout == 0)
  358                                 return (-1);
  359                 }
  360                 data[read] = TI_SPI_READ(sc, MCSPI_RX_CH(sc->sc_cs));
  361         }
  362 
  363         return (0);
  364 }
  365 
  366 static void
  367 ti_spi_intr(void *arg)
  368 {
  369         struct ti_spi_softc *sc;
  370         uint32_t status;
  371 
  372         sc = (struct ti_spi_softc *)arg;
  373         TI_SPI_LOCK(sc);
  374         status = TI_SPI_READ(sc, MCSPI_IRQSTATUS);
  375 
  376         /*
  377          * No new TX_empty or RX_full event will be asserted while the CPU has
  378          * not performed the number of writes or reads defined by
  379          * MCSPI_XFERLEVEL[AEL] and MCSPI_XFERLEVEL[AFL].  It is responsibility
  380          * of CPU perform the right number of writes and reads.
  381          */
  382         if (status & MCSPI_IRQ_TX0_EMPTY)
  383                 ti_spi_fill_fifo(sc);
  384         if (status & MCSPI_IRQ_RX0_FULL)
  385                 ti_spi_drain_fifo(sc);
  386 
  387         /* Clear interrupt status. */
  388         TI_SPI_WRITE(sc, MCSPI_IRQSTATUS, status);
  389 
  390         /* Check for end of transfer. */
  391         if (sc->sc_written == sc->sc_len && sc->sc_read == sc->sc_len) {
  392                 sc->sc_flags |= TI_SPI_DONE;
  393                 wakeup(sc->sc_dev);
  394         }
  395 
  396         TI_SPI_UNLOCK(sc);
  397 }
  398 
  399 static int
  400 ti_spi_pio_transfer(struct ti_spi_softc *sc)
  401 {
  402 
  403         while (sc->sc_len - sc->sc_written > 0) {
  404                 if (ti_spi_fill_fifo(sc) == -1)
  405                         return (EIO);
  406                 if (ti_spi_drain_fifo(sc) == -1)
  407                         return (EIO);
  408         }
  409 
  410         return (0);
  411 }
  412 
  413 static int
  414 ti_spi_gcd(int a, int b)
  415 {
  416         int m;
  417 
  418         while ((m = a % b) != 0) {
  419                 a = b;
  420                 b = m;
  421         }
  422 
  423         return (b);
  424 }
  425 
  426 static int
  427 ti_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
  428 {
  429         int err;
  430         struct ti_spi_softc *sc;
  431         uint32_t clockhz, cs, mode, reg;
  432 
  433         sc = device_get_softc(dev);
  434 
  435         KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, 
  436             ("TX/RX command sizes should be equal"));
  437         KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 
  438             ("TX/RX data sizes should be equal"));
  439 
  440         /* Get the proper chip select for this child. */
  441         spibus_get_cs(child, &cs);
  442         spibus_get_clock(child, &clockhz);
  443         spibus_get_mode(child, &mode);
  444 
  445         cs &= ~SPIBUS_CS_HIGH;
  446 
  447         if (cs > sc->sc_numcs) {
  448                 device_printf(dev, "Invalid chip select %d requested by %s\n",
  449                     cs, device_get_nameunit(child));
  450                 return (EINVAL);
  451         }
  452 
  453         if (mode > 3)
  454         {
  455             device_printf(dev, "Invalid mode %d requested by %s\n", mode,
  456                     device_get_nameunit(child));
  457             return (EINVAL);
  458         }
  459 
  460         TI_SPI_LOCK(sc);
  461 
  462         /* If the controller is in use wait until it is available. */
  463         while (sc->sc_flags & TI_SPI_BUSY)
  464                 mtx_sleep(dev, &sc->sc_mtx, 0, "ti_spi", 0);
  465 
  466         /* Now we have control over SPI controller. */
  467         sc->sc_flags = TI_SPI_BUSY;
  468 
  469         /* Save the SPI command data. */
  470         sc->sc_cs = cs;
  471         sc->sc_cmd = cmd;
  472         sc->sc_read = 0;
  473         sc->sc_written = 0;
  474         sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz;
  475         sc->sc_fifolvl = ti_spi_gcd(sc->sc_len, TI_SPI_FIFOSZ);
  476         if (sc->sc_fifolvl < 2 || sc->sc_len > 0xffff)
  477                 sc->sc_fifolvl = 1;     /* FIFO disabled. */
  478         /* Disable FIFO for now. */
  479         sc->sc_fifolvl = 1;
  480 
  481         /* Set the bus frequency. */
  482         ti_spi_set_clock(sc, sc->sc_cs, clockhz);
  483 
  484         /* Disable the FIFO. */
  485         TI_SPI_WRITE(sc, MCSPI_XFERLEVEL, 0);
  486 
  487         /* 8 bits word, d0 miso, d1 mosi, mode 0 and CS active low. */
  488         reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
  489         reg &= ~(MCSPI_CONF_FFER | MCSPI_CONF_FFEW | MCSPI_CONF_SBPOL |
  490             MCSPI_CONF_SBE | MCSPI_CONF_TURBO | MCSPI_CONF_IS |
  491             MCSPI_CONF_DPE1 | MCSPI_CONF_DPE0 | MCSPI_CONF_DMAR |
  492             MCSPI_CONF_DMAW | MCSPI_CONF_EPOL);
  493         reg |= MCSPI_CONF_DPE0 | MCSPI_CONF_EPOL | MCSPI_CONF_WL8BITS;
  494         reg |= mode; /* POL and PHA are the low bits, we can just OR-in mode */
  495         TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg);
  496 
  497 #if 0
  498         /* Enable channel interrupts. */
  499         reg = TI_SPI_READ(sc, MCSPI_IRQENABLE);
  500         reg |= 0xf;
  501         TI_SPI_WRITE(sc, MCSPI_IRQENABLE, reg);
  502 #endif
  503 
  504         /* Start the transfer. */
  505         reg = TI_SPI_READ(sc, MCSPI_CTRL_CH(sc->sc_cs));
  506         TI_SPI_WRITE(sc, MCSPI_CTRL_CH(sc->sc_cs), reg | MCSPI_CTRL_ENABLE);
  507 
  508         /* Force CS on. */
  509         reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
  510         TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg |= MCSPI_CONF_FORCE);
  511 
  512         err = 0;
  513         if (sc->sc_fifolvl == 1)
  514                 err = ti_spi_pio_transfer(sc);
  515 
  516         /* Force CS off. */
  517         reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
  518         reg &= ~MCSPI_CONF_FORCE;
  519         TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg);
  520 
  521         /* Disable IRQs. */
  522         reg = TI_SPI_READ(sc, MCSPI_IRQENABLE);
  523         reg &= ~0xf;
  524         TI_SPI_WRITE(sc, MCSPI_IRQENABLE, reg);
  525         TI_SPI_WRITE(sc, MCSPI_IRQSTATUS, 0xf);
  526 
  527         /* Disable the SPI channel. */
  528         reg = TI_SPI_READ(sc, MCSPI_CTRL_CH(sc->sc_cs));
  529         reg &= ~MCSPI_CTRL_ENABLE;
  530         TI_SPI_WRITE(sc, MCSPI_CTRL_CH(sc->sc_cs), reg);
  531 
  532         /* Disable FIFO. */
  533         reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
  534         reg &= ~(MCSPI_CONF_FFER | MCSPI_CONF_FFEW);
  535         TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg);
  536 
  537         /* Release the controller and wakeup the next thread waiting for it. */
  538         sc->sc_flags = 0;
  539         wakeup_one(dev);
  540         TI_SPI_UNLOCK(sc);
  541 
  542         return (err);
  543 }
  544 
  545 static phandle_t
  546 ti_spi_get_node(device_t bus, device_t dev)
  547 {
  548 
  549         /* Share controller node with spibus. */
  550         return (ofw_bus_get_node(bus));
  551 }
  552 
  553 static device_method_t ti_spi_methods[] = {
  554         /* Device interface */
  555         DEVMETHOD(device_probe,         ti_spi_probe),
  556         DEVMETHOD(device_attach,        ti_spi_attach),
  557         DEVMETHOD(device_detach,        ti_spi_detach),
  558 
  559         /* SPI interface */
  560         DEVMETHOD(spibus_transfer,      ti_spi_transfer),
  561 
  562         /* ofw_bus interface */
  563         DEVMETHOD(ofw_bus_get_node,     ti_spi_get_node),
  564 
  565         DEVMETHOD_END
  566 };
  567 
  568 static driver_t ti_spi_driver = {
  569         "spi",
  570         ti_spi_methods,
  571         sizeof(struct ti_spi_softc),
  572 };
  573 
  574 DRIVER_MODULE(ti_spi, simplebus, ti_spi_driver, 0, 0);
  575 MODULE_DEPEND(ti_spi, ti_sysc, 1, 1, 1);

Cache object: d7934133fb725ec479ecea9fd1a3a1f3


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