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/intel/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 Oleksandr Tymoshenko <gonzo@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_acpi.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/bus.h>
   34 #include <sys/kernel.h>
   35 #include <sys/module.h>
   36 #include <sys/proc.h>
   37 #include <sys/rman.h>
   38 
   39 #include <machine/bus.h>
   40 #include <machine/resource.h>
   41 
   42 #include <dev/spibus/spi.h>
   43 #include <dev/spibus/spibusvar.h>
   44 
   45 #include <contrib/dev/acpica/include/acpi.h>
   46 #include <contrib/dev/acpica/include/accommon.h>
   47 
   48 #include <dev/acpica/acpivar.h>
   49 
   50 #include "spibus_if.h"
   51 
   52 /**
   53  *      Macros for driver mutex locking
   54  */
   55 #define INTELSPI_LOCK(_sc)              mtx_lock(&(_sc)->sc_mtx)
   56 #define INTELSPI_UNLOCK(_sc)            mtx_unlock(&(_sc)->sc_mtx)
   57 #define INTELSPI_LOCK_INIT(_sc)         \
   58         mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
   59             "intelspi", MTX_DEF)
   60 #define INTELSPI_LOCK_DESTROY(_sc)      mtx_destroy(&(_sc)->sc_mtx)
   61 #define INTELSPI_ASSERT_LOCKED(_sc)     mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
   62 #define INTELSPI_ASSERT_UNLOCKED(_sc)   mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
   63 
   64 #define INTELSPI_WRITE(_sc, _off, _val)         \
   65     bus_write_4((_sc)->sc_mem_res, (_off), (_val))
   66 #define INTELSPI_READ(_sc, _off)                        \
   67     bus_read_4((_sc)->sc_mem_res, (_off))
   68 
   69 #define INTELSPI_BUSY           0x1
   70 #define TX_FIFO_THRESHOLD       2
   71 #define RX_FIFO_THRESHOLD       2
   72 #define CLOCK_DIV_10MHZ         5
   73 #define DATA_SIZE_8BITS         8
   74 
   75 #define CS_LOW          0
   76 #define CS_HIGH         1
   77 
   78 #define INTELSPI_SSPREG_SSCR0           0x0
   79 #define  SSCR0_SCR(n)                           (((n) - 1) << 8)
   80 #define  SSCR0_SSE                              (1 << 7)
   81 #define  SSCR0_FRF_SPI                          (0 << 4)
   82 #define  SSCR0_DSS(n)                           (((n) - 1) << 0)
   83 #define INTELSPI_SSPREG_SSCR1           0x4
   84 #define  SSCR1_TINTE                            (1 << 19)
   85 #define  SSCR1_RFT(n)                           (((n) - 1) << 10)
   86 #define  SSCR1_RFT_MASK                         (0xf << 10)
   87 #define  SSCR1_TFT(n)                           (((n) - 1) << 6)
   88 #define  SSCR1_SPI_SPH                          (1 << 4)
   89 #define  SSCR1_SPI_SPO                          (1 << 3)
   90 #define  SSCR1_MODE_MASK                                (SSCR1_SPI_SPO | SSCR1_SPI_SPH)
   91 #define  SSCR1_MODE_0                           (0)
   92 #define  SSCR1_MODE_1                           (SSCR1_SPI_SPH)
   93 #define  SSCR1_MODE_2                           (SSCR1_SPI_SPO)
   94 #define  SSCR1_MODE_3                           (SSCR1_SPI_SPO | SSCR1_SPI_SPH)
   95 #define  SSCR1_TIE                              (1 << 1)
   96 #define  SSCR1_RIE                              (1 << 0)
   97 #define INTELSPI_SSPREG_SSSR            0x8
   98 #define  SSSR_RFL_MASK                          (0xf << 12)
   99 #define  SSSR_TFL_MASK                          (0xf << 8)
  100 #define  SSSR_RNE                               (1 << 3)
  101 #define  SSSR_TNF                               (1 << 2)
  102 #define INTELSPI_SSPREG_SSITR           0xC
  103 #define INTELSPI_SSPREG_SSDR            0x10
  104 #define INTELSPI_SSPREG_SSTO            0x28
  105 #define INTELSPI_SSPREG_SSPSP           0x2C
  106 #define INTELSPI_SSPREG_SSTSA           0x30
  107 #define INTELSPI_SSPREG_SSRSA           0x34
  108 #define INTELSPI_SSPREG_SSTSS           0x38
  109 #define INTELSPI_SSPREG_SSACD           0x3C
  110 #define INTELSPI_SSPREG_ITF             0x40
  111 #define INTELSPI_SSPREG_SITF            0x44
  112 #define INTELSPI_SSPREG_SIRF            0x48
  113 #define INTELSPI_SSPREG_PRV_CLOCK_PARAMS        0x400
  114 #define INTELSPI_SSPREG_RESETS          0x404
  115 #define INTELSPI_SSPREG_GENERAL         0x408
  116 #define INTELSPI_SSPREG_SSP_REG         0x40C
  117 #define INTELSPI_SSPREG_SPI_CS_CTRL      0x418
  118 #define  SPI_CS_CTRL_CS_MASK                    (3)
  119 #define  SPI_CS_CTRL_SW_MODE                    (1 << 0)
  120 #define  SPI_CS_CTRL_HW_MODE                    (1 << 0)
  121 #define  SPI_CS_CTRL_CS_HIGH                    (1 << 1)
  122 #define  SPI_CS_CTRL_CS_LOW                     (0 << 1)
  123 
  124 struct intelspi_softc {
  125         ACPI_HANDLE             sc_handle;
  126         device_t                sc_dev;
  127         struct mtx              sc_mtx;
  128         int                     sc_mem_rid;
  129         struct resource         *sc_mem_res;
  130         int                     sc_irq_rid;
  131         struct resource         *sc_irq_res;
  132         void                    *sc_irq_ih;
  133         struct spi_command      *sc_cmd;
  134         uint32_t                sc_len;
  135         uint32_t                sc_read;
  136         uint32_t                sc_flags;
  137         uint32_t                sc_written;
  138 };
  139 
  140 static int      intelspi_probe(device_t dev);
  141 static int      intelspi_attach(device_t dev);
  142 static int      intelspi_detach(device_t dev);
  143 static void     intelspi_intr(void *);
  144 
  145 static int
  146 intelspi_txfifo_full(struct intelspi_softc *sc)
  147 {
  148         uint32_t sssr;
  149 
  150         INTELSPI_ASSERT_LOCKED(sc);
  151 
  152         sssr = INTELSPI_READ(sc, INTELSPI_SSPREG_SSSR);
  153         if (sssr & SSSR_TNF)
  154                 return (0);
  155 
  156         return (1);
  157 }
  158 
  159 static int
  160 intelspi_rxfifo_empty(struct intelspi_softc *sc)
  161 {
  162         uint32_t sssr;
  163 
  164         INTELSPI_ASSERT_LOCKED(sc);
  165 
  166         sssr = INTELSPI_READ(sc, INTELSPI_SSPREG_SSSR);
  167         if (sssr & SSSR_RNE)
  168                 return (0);
  169         else
  170                 return (1);
  171 }
  172 
  173 static void
  174 intelspi_fill_tx_fifo(struct intelspi_softc *sc)
  175 {
  176         struct spi_command *cmd;
  177         uint32_t written;
  178         uint8_t *data;
  179 
  180         INTELSPI_ASSERT_LOCKED(sc);
  181 
  182         cmd = sc->sc_cmd;
  183         while (sc->sc_written < sc->sc_len &&
  184             !intelspi_txfifo_full(sc)) {
  185                 data = (uint8_t *)cmd->tx_cmd;
  186                 written = sc->sc_written++;
  187 
  188                 if (written >= cmd->tx_cmd_sz) {
  189                         data = (uint8_t *)cmd->tx_data;
  190                         written -= cmd->tx_cmd_sz;
  191                 }
  192                 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSDR, data[written]);
  193         }
  194 }
  195 
  196 static void
  197 intelspi_drain_rx_fifo(struct intelspi_softc *sc)
  198 {
  199         struct spi_command *cmd;
  200         uint32_t  read;
  201         uint8_t *data;
  202 
  203         INTELSPI_ASSERT_LOCKED(sc);
  204 
  205         cmd = sc->sc_cmd;
  206         while (sc->sc_read < sc->sc_len &&
  207             !intelspi_rxfifo_empty(sc)) {
  208                 data = (uint8_t *)cmd->rx_cmd;
  209                 read = sc->sc_read++;
  210                 if (read >= cmd->rx_cmd_sz) {
  211                         data = (uint8_t *)cmd->rx_data;
  212                         read -= cmd->rx_cmd_sz;
  213                 }
  214                 data[read] = INTELSPI_READ(sc, INTELSPI_SSPREG_SSDR) & 0xff;
  215         }
  216 }
  217 
  218 static int
  219 intelspi_transaction_done(struct intelspi_softc *sc)
  220 {
  221         int txfifo_empty;
  222         uint32_t sssr;
  223 
  224         INTELSPI_ASSERT_LOCKED(sc);
  225 
  226         if (sc->sc_written != sc->sc_len ||
  227             sc->sc_read != sc->sc_len)
  228                 return (0);
  229 
  230         sssr = INTELSPI_READ(sc, INTELSPI_SSPREG_SSSR);
  231         txfifo_empty = ((sssr & SSSR_TFL_MASK) == 0) &&
  232                 (sssr & SSSR_TNF);
  233 
  234         if (txfifo_empty && !(sssr & SSSR_RNE))
  235                 return (1);
  236 
  237         return (0);
  238 }
  239 
  240 static int
  241 intelspi_transact(struct intelspi_softc *sc)
  242 {
  243 
  244         INTELSPI_ASSERT_LOCKED(sc);
  245 
  246         /* TX - Fill up the FIFO. */
  247         intelspi_fill_tx_fifo(sc);
  248 
  249         /* RX - Drain the FIFO. */
  250         intelspi_drain_rx_fifo(sc);
  251 
  252         /* Check for end of transfer. */
  253         return intelspi_transaction_done(sc);
  254 }
  255 
  256 static void
  257 intelspi_intr(void *arg)
  258 {
  259         struct intelspi_softc *sc;
  260         uint32_t reg;
  261 
  262         sc = (struct intelspi_softc *)arg;
  263 
  264         INTELSPI_LOCK(sc);
  265         if ((sc->sc_flags & INTELSPI_BUSY) == 0) {
  266                 INTELSPI_UNLOCK(sc);
  267                 return;
  268         }
  269 
  270         /* Check if SSP if off */
  271         reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SSSR);
  272         if (reg == 0xffffffffU) {
  273                 INTELSPI_UNLOCK(sc);
  274                 return;
  275         }
  276 
  277         /* Check for end of transfer. */
  278         if (intelspi_transact(sc)) {
  279                 /* Disable interrupts */
  280                 reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1);
  281                 reg &= ~(SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE);
  282                 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, reg);
  283                 wakeup(sc->sc_dev);
  284         }
  285 
  286         INTELSPI_UNLOCK(sc);
  287 }
  288 
  289 static void
  290 intelspi_init(struct intelspi_softc *sc)
  291 {
  292         uint32_t reg;
  293 
  294         INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, 0);
  295 
  296         /* Manual CS control */
  297         reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SPI_CS_CTRL);
  298         reg &= ~(SPI_CS_CTRL_CS_MASK);
  299         reg |= (SPI_CS_CTRL_SW_MODE | SPI_CS_CTRL_CS_HIGH);
  300         INTELSPI_WRITE(sc, INTELSPI_SSPREG_SPI_CS_CTRL, reg);
  301 
  302         /* Set TX/RX FIFO IRQ threshold levels */
  303         reg = SSCR1_TFT(TX_FIFO_THRESHOLD) | SSCR1_RFT(RX_FIFO_THRESHOLD);
  304         /*
  305          * Set SPI mode. This should be part of transaction or sysctl
  306          */
  307         reg |= SSCR1_MODE_0;
  308         INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, reg);
  309 
  310         /*
  311          * Parent clock on Minowboard Turbot is 50MHz
  312          * divide it by 5 to set to more or less reasonable
  313          * value. But this should be part of transaction config
  314          * or sysctl
  315          */
  316         reg = SSCR0_SCR(CLOCK_DIV_10MHZ);
  317         /* Put SSP in SPI mode */
  318         reg |= SSCR0_FRF_SPI;
  319         /* Data size */
  320         reg |= SSCR0_DSS(DATA_SIZE_8BITS);
  321         /* Enable SSP */
  322         reg |= SSCR0_SSE;
  323         INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, reg);
  324 }
  325 
  326 static void
  327 intelspi_set_cs(struct intelspi_softc *sc, int level)
  328 {
  329         uint32_t reg;
  330 
  331         reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SPI_CS_CTRL);
  332         reg &= ~(SPI_CS_CTRL_CS_MASK);
  333         reg |= SPI_CS_CTRL_SW_MODE;
  334 
  335         if (level == CS_HIGH)
  336                 reg |= SPI_CS_CTRL_CS_HIGH;
  337         else
  338                 reg |= SPI_CS_CTRL_CS_LOW;
  339                 
  340         INTELSPI_WRITE(sc, INTELSPI_SSPREG_SPI_CS_CTRL, reg);
  341 }
  342 
  343 static int
  344 intelspi_transfer(device_t dev, device_t child, struct spi_command *cmd)
  345 {
  346         struct intelspi_softc *sc;
  347         int err;
  348         uint32_t sscr1;
  349 
  350         sc = device_get_softc(dev);
  351         err = 0;
  352 
  353         KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, 
  354             ("TX/RX command sizes should be equal"));
  355         KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 
  356             ("TX/RX data sizes should be equal"));
  357 
  358         INTELSPI_LOCK(sc);
  359 
  360         /* If the controller is in use wait until it is available. */
  361         while (sc->sc_flags & INTELSPI_BUSY) {
  362                 err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", 0);
  363                 if (err == EINTR) {
  364                         INTELSPI_UNLOCK(sc);
  365                         return (err);
  366                 }
  367         }
  368 
  369         /* Now we have control over SPI controller. */
  370         sc->sc_flags = INTELSPI_BUSY;
  371 
  372         /* Save a pointer to the SPI command. */
  373         sc->sc_cmd = cmd;
  374         sc->sc_read = 0;
  375         sc->sc_written = 0;
  376         sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz;
  377 
  378         /* Enable CS */
  379         intelspi_set_cs(sc, CS_LOW);
  380         /* Transfer as much as possible to FIFOs */
  381         if (!intelspi_transact(sc)) {
  382                 /* If FIFO is not large enough - enable interrupts */
  383                 sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1);
  384                 sscr1 |= (SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE);
  385                 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1);
  386 
  387                 /* and wait for transaction to complete */
  388                 err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", hz * 2);
  389         }
  390 
  391         /* de-asser CS */
  392         intelspi_set_cs(sc, CS_HIGH);
  393 
  394         /* Clear transaction details */
  395         sc->sc_cmd = NULL;
  396         sc->sc_read = 0;
  397         sc->sc_written = 0;
  398         sc->sc_len = 0;
  399 
  400         /* Make sure the SPI engine and interrupts are disabled. */
  401         sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1);
  402         sscr1 &= ~(SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE);
  403         INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1);
  404 
  405         /* Release the controller and wakeup the next thread waiting for it. */
  406         sc->sc_flags = 0;
  407         wakeup_one(dev);
  408         INTELSPI_UNLOCK(sc);
  409 
  410         /*
  411          * Check for transfer timeout.  The SPI controller doesn't
  412          * return errors.
  413          */
  414         if (err == EWOULDBLOCK) {
  415                 device_printf(sc->sc_dev, "transfer timeout\n");
  416                 err = EIO;
  417         }
  418 
  419         return (err);
  420 }
  421 
  422 static int
  423 intelspi_probe(device_t dev)
  424 {
  425         static char *gpio_ids[] = { "80860F0E", NULL };
  426 
  427         if (acpi_disabled("spi") ||
  428             ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids) == NULL)
  429         return (ENXIO);
  430 
  431         device_set_desc(dev, "Intel SPI Controller");
  432         return (0);
  433 }
  434 
  435 static int
  436 intelspi_attach(device_t dev)
  437 {
  438         struct intelspi_softc   *sc;
  439 
  440         sc = device_get_softc(dev);
  441         sc->sc_dev = dev;
  442         sc->sc_handle = acpi_get_handle(dev);
  443 
  444         INTELSPI_LOCK_INIT(sc);
  445 
  446         sc->sc_mem_rid = 0;
  447         sc->sc_mem_res = bus_alloc_resource_any(sc->sc_dev,
  448             SYS_RES_MEMORY, &sc->sc_mem_rid, RF_ACTIVE);
  449         if (sc->sc_mem_res == NULL) {
  450                 device_printf(dev, "can't allocate memory resource\n");
  451                 goto error;
  452         }
  453 
  454         sc->sc_irq_rid = 0;
  455         sc->sc_irq_res = bus_alloc_resource_any(sc->sc_dev,
  456             SYS_RES_IRQ, &sc->sc_irq_rid, RF_ACTIVE);
  457         if (sc->sc_irq_res == NULL) {
  458                 device_printf(dev, "can't allocate IRQ resource\n");
  459                 goto error;
  460         }
  461 
  462         /* Hook up our interrupt handler. */
  463         if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
  464             NULL, intelspi_intr, sc, &sc->sc_irq_ih)) {
  465                 device_printf(dev, "cannot setup the interrupt handler\n");
  466                 goto error;
  467         }
  468 
  469         intelspi_init(sc);
  470 
  471         device_add_child(dev, "spibus", -1);
  472 
  473         return (bus_generic_attach(dev));
  474 
  475 error:
  476         INTELSPI_LOCK_DESTROY(sc);
  477 
  478         if (sc->sc_mem_res != NULL)
  479                 bus_release_resource(dev, SYS_RES_MEMORY,
  480                     sc->sc_mem_rid, sc->sc_mem_res);
  481 
  482         if (sc->sc_irq_res != NULL)
  483                 bus_release_resource(dev, SYS_RES_IRQ,
  484                     sc->sc_irq_rid, sc->sc_irq_res);
  485 
  486         return (ENXIO);
  487 }
  488 
  489 static int
  490 intelspi_detach(device_t dev)
  491 {
  492         struct intelspi_softc   *sc;
  493 
  494         sc = device_get_softc(dev);
  495 
  496         INTELSPI_LOCK_DESTROY(sc);
  497 
  498         if (sc->sc_irq_ih)
  499                 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_ih);
  500 
  501         if (sc->sc_mem_res != NULL)
  502                 bus_release_resource(dev, SYS_RES_MEMORY,
  503                     sc->sc_mem_rid, sc->sc_mem_res);
  504 
  505         if (sc->sc_irq_res != NULL)
  506                 bus_release_resource(dev, SYS_RES_IRQ,
  507                     sc->sc_irq_rid, sc->sc_irq_res);
  508 
  509         return (bus_generic_detach(dev));
  510 }
  511 
  512 static device_method_t intelspi_methods[] = {
  513         /* Device interface */
  514         DEVMETHOD(device_probe, intelspi_probe),
  515         DEVMETHOD(device_attach, intelspi_attach),
  516         DEVMETHOD(device_detach, intelspi_detach),
  517 
  518         /* SPI interface */
  519         DEVMETHOD(spibus_transfer,      intelspi_transfer),
  520 
  521         DEVMETHOD_END
  522 };
  523 
  524 static driver_t intelspi_driver = {
  525         "spi",
  526         intelspi_methods,
  527         sizeof(struct intelspi_softc),
  528 };
  529 
  530 static devclass_t intelspi_devclass;
  531 DRIVER_MODULE(intelspi, acpi, intelspi_driver, intelspi_devclass, 0, 0);
  532 MODULE_DEPEND(intelspi, acpi, 1, 1, 1);
  533 MODULE_DEPEND(intelspi, spibus, 1, 1, 1);

Cache object: 4442772c99795e0808e30d8e12a05090


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