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/flash/cqspi.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) 2017-2018 Ruslan Bukin <br@bsdpad.com>
    3  * All rights reserved.
    4  *
    5  * This software was developed by SRI International and the University of
    6  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
    7  * ("CTSRD"), as part of the DARPA CRASH research programme.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * Cadence Quad SPI Flash Controller driver.
   33  * 4B-addressing mode supported only.
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD: releng/12.0/sys/dev/flash/cqspi.c 332885 2018-04-23 10:35:00Z br $");
   38 
   39 #include "opt_platform.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/bio.h>
   44 #include <sys/bus.h>
   45 #include <sys/conf.h>
   46 #include <sys/kernel.h>
   47 #include <sys/kthread.h>
   48 #include <sys/lock.h>
   49 #include <sys/mbuf.h>
   50 #include <sys/malloc.h>
   51 #include <sys/module.h>
   52 #include <sys/mutex.h>
   53 #include <geom/geom_disk.h>
   54 
   55 #include <machine/bus.h>
   56 
   57 #include <dev/fdt/simplebus.h>
   58 #include <dev/fdt/fdt_common.h>
   59 #include <dev/ofw/ofw_bus_subr.h>
   60 #include <dev/ofw/openfirm.h>
   61 
   62 #include <dev/flash/cqspi.h>
   63 #include <dev/flash/mx25lreg.h>
   64 #include <dev/xdma/xdma.h>
   65 
   66 #include "qspi_if.h"
   67 
   68 #define CQSPI_DEBUG
   69 #undef CQSPI_DEBUG
   70 
   71 #ifdef CQSPI_DEBUG
   72 #define dprintf(fmt, ...)  printf(fmt, ##__VA_ARGS__)
   73 #else
   74 #define dprintf(fmt, ...)
   75 #endif
   76 
   77 #define CQSPI_SECTORSIZE        512
   78 #define TX_QUEUE_SIZE           16
   79 #define RX_QUEUE_SIZE           16
   80 
   81 #define READ4(_sc, _reg) bus_read_4((_sc)->res[0], _reg)
   82 #define READ2(_sc, _reg) bus_read_2((_sc)->res[0], _reg)
   83 #define READ1(_sc, _reg) bus_read_1((_sc)->res[0], _reg)
   84 #define WRITE4(_sc, _reg, _val) bus_write_4((_sc)->res[0], _reg, _val)
   85 #define WRITE2(_sc, _reg, _val) bus_write_2((_sc)->res[0], _reg, _val)
   86 #define WRITE1(_sc, _reg, _val) bus_write_1((_sc)->res[0], _reg, _val)
   87 #define READ_DATA_4(_sc, _reg) bus_read_4((_sc)->res[1], _reg)
   88 #define READ_DATA_1(_sc, _reg) bus_read_1((_sc)->res[1], _reg)
   89 #define WRITE_DATA_4(_sc, _reg, _val) bus_write_4((_sc)->res[1], _reg, _val)
   90 #define WRITE_DATA_1(_sc, _reg, _val) bus_write_1((_sc)->res[1], _reg, _val)
   91 
   92 struct cqspi_softc {
   93         device_t                dev;
   94 
   95         struct resource         *res[3];
   96         bus_space_tag_t         bst;
   97         bus_space_handle_t      bsh;
   98         void                    *ih;
   99         uint8_t                 read_op_done;
  100         uint8_t                 write_op_done;
  101 
  102         uint32_t                fifo_depth;
  103         uint32_t                fifo_width;
  104         uint32_t                trigger_address;
  105         uint32_t                sram_phys;
  106 
  107         /* xDMA */
  108         xdma_controller_t       *xdma_tx;
  109         xdma_channel_t          *xchan_tx;
  110         void                    *ih_tx;
  111 
  112         xdma_controller_t       *xdma_rx;
  113         xdma_channel_t          *xchan_rx;
  114         void                    *ih_rx;
  115 
  116         struct intr_config_hook config_intrhook;
  117         struct mtx              sc_mtx;
  118 };
  119 
  120 #define CQSPI_LOCK(_sc)         mtx_lock(&(_sc)->sc_mtx)
  121 #define CQSPI_UNLOCK(_sc)       mtx_unlock(&(_sc)->sc_mtx)
  122 #define CQSPI_LOCK_INIT(_sc)                                    \
  123         mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev),   \
  124             "cqspi", MTX_DEF)
  125 #define CQSPI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
  126 #define CQSPI_ASSERT_LOCKED(_sc)                                \
  127         mtx_assert(&_sc->sc_mtx, MA_OWNED);
  128 #define CQSPI_ASSERT_UNLOCKED(_sc)                              \
  129         mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
  130 
  131 static struct resource_spec cqspi_spec[] = {
  132         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
  133         { SYS_RES_MEMORY,       1,      RF_ACTIVE },
  134         { SYS_RES_IRQ,          0,      RF_ACTIVE },
  135         { -1, 0 }
  136 };
  137 
  138 static struct ofw_compat_data compat_data[] = {
  139         { "cdns,qspi-nor",      1 },
  140         { NULL,                 0 },
  141 };
  142 
  143 static void
  144 cqspi_intr(void *arg)
  145 {
  146         struct cqspi_softc *sc;
  147         uint32_t pending;
  148 
  149         sc = arg;
  150 
  151         pending = READ4(sc, CQSPI_IRQSTAT);
  152 
  153         dprintf("%s: IRQSTAT %x\n", __func__, pending);
  154 
  155         if (pending & (IRQMASK_INDOPDONE | IRQMASK_INDXFRLVL |
  156             IRQMASK_INDSRAMFULL)) {
  157                 /* TODO: PIO operation done */
  158         }
  159 
  160         WRITE4(sc, CQSPI_IRQSTAT, pending);
  161 }
  162 
  163 static int
  164 cqspi_xdma_tx_intr(void *arg, xdma_transfer_status_t *status)
  165 {
  166         struct xdma_transfer_status st;
  167         struct cqspi_softc *sc;
  168         struct bio *bp;
  169         int ret;
  170         int deq;
  171 
  172         sc = arg;
  173 
  174         dprintf("%s\n", __func__);
  175 
  176         deq = 0;
  177 
  178         while (1) {
  179                 ret = xdma_dequeue_bio(sc->xchan_tx, &bp, &st);
  180                 if (ret != 0) {
  181                         break;
  182                 }
  183                 sc->write_op_done = 1;
  184                 deq++;
  185         }
  186 
  187         if (deq > 1)
  188                 device_printf(sc->dev,
  189                     "Warning: more than 1 tx bio dequeued\n");
  190 
  191         wakeup(&sc->xdma_tx);
  192 
  193         return (0);
  194 }
  195 
  196 static int
  197 cqspi_xdma_rx_intr(void *arg, xdma_transfer_status_t *status)
  198 {
  199         struct xdma_transfer_status st;
  200         struct cqspi_softc *sc;
  201         struct bio *bp;
  202         int ret;
  203         int deq;
  204 
  205         sc = arg;
  206 
  207         dprintf("%s\n", __func__);
  208 
  209         deq = 0;
  210 
  211         while (1) {
  212                 ret = xdma_dequeue_bio(sc->xchan_rx, &bp, &st);
  213                 if (ret != 0) {
  214                         break;
  215                 }
  216                 sc->read_op_done = 1;
  217                 deq++;
  218         }
  219 
  220         if (deq > 1)
  221                 device_printf(sc->dev,
  222                     "Warning: more than 1 rx bio dequeued\n");
  223 
  224         wakeup(&sc->xdma_rx);
  225 
  226         return (0);
  227 }
  228 
  229 static int
  230 cqspi_wait_for_completion(struct cqspi_softc *sc)
  231 {
  232         int timeout;
  233         int i;
  234 
  235         timeout = 10000;
  236 
  237         for (i = timeout; i > 0; i--) {
  238                 if ((READ4(sc, CQSPI_FLASHCMD) & FLASHCMD_CMDEXECSTAT) == 0) {
  239                         break;
  240                 }
  241         }
  242 
  243         if (i == 0) {
  244                 device_printf(sc->dev, "%s: cmd timed out: %x\n",
  245                     __func__, READ4(sc, CQSPI_FLASHCMD));
  246                 return (-1);
  247         }
  248 
  249         return (0);
  250 }
  251 
  252 static int
  253 cqspi_cmd_write_addr(struct cqspi_softc *sc, uint8_t cmd,
  254     uint32_t addr, uint32_t len)
  255 {
  256         uint32_t reg;
  257         int ret;
  258 
  259         dprintf("%s: %x\n", __func__, cmd);
  260 
  261         WRITE4(sc, CQSPI_FLASHCMDADDR, addr);
  262         reg = (cmd << FLASHCMD_CMDOPCODE_S);
  263         reg |= (FLASHCMD_ENCMDADDR);
  264         reg |= ((len - 1) << FLASHCMD_NUMADDRBYTES_S);
  265         WRITE4(sc, CQSPI_FLASHCMD, reg);
  266 
  267         reg |= FLASHCMD_EXECCMD;
  268         WRITE4(sc, CQSPI_FLASHCMD, reg);
  269 
  270         ret = cqspi_wait_for_completion(sc);
  271 
  272         return (ret);
  273 }
  274 
  275 static int
  276 cqspi_cmd_write(struct cqspi_softc *sc, uint8_t cmd,
  277     uint8_t *addr, uint32_t len)
  278 {
  279         uint32_t reg;
  280         int ret;
  281 
  282         reg = (cmd << FLASHCMD_CMDOPCODE_S);
  283         WRITE4(sc, CQSPI_FLASHCMD, reg);
  284         reg |= FLASHCMD_EXECCMD;
  285         WRITE4(sc, CQSPI_FLASHCMD, reg);
  286 
  287         ret = cqspi_wait_for_completion(sc);
  288 
  289         return (ret);
  290 }
  291 
  292 static int
  293 cqspi_cmd_read(struct cqspi_softc *sc, uint8_t cmd,
  294     uint8_t *addr, uint32_t len)
  295 {
  296         uint32_t data;
  297         uint32_t reg;
  298         uint8_t *buf;
  299         int ret;
  300         int i;
  301 
  302         if (len > 8) {
  303                 device_printf(sc->dev, "Failed to read data\n");
  304                 return (-1);
  305         }
  306 
  307         dprintf("%s: %x\n", __func__, cmd);
  308 
  309         buf = (uint8_t *)addr;
  310 
  311         reg = (cmd << FLASHCMD_CMDOPCODE_S);
  312         reg |= ((len - 1) << FLASHCMD_NUMRDDATABYTES_S);
  313         reg |= FLASHCMD_ENRDDATA;
  314         WRITE4(sc, CQSPI_FLASHCMD, reg);
  315 
  316         reg |= FLASHCMD_EXECCMD;
  317         WRITE4(sc, CQSPI_FLASHCMD, reg);
  318 
  319         ret = cqspi_wait_for_completion(sc);
  320         if (ret != 0) {
  321                 device_printf(sc->dev, "%s: cmd failed: %x\n",
  322                     __func__, cmd);
  323                 return (ret);
  324         }
  325 
  326         data = READ4(sc, CQSPI_FLASHCMDRDDATALO);
  327 
  328         for (i = 0; i < len; i++)
  329                 buf[i] = (data >> (i * 8)) & 0xff;
  330 
  331         return (0);
  332 }
  333 
  334 static int
  335 cqspi_wait_ready(struct cqspi_softc *sc)
  336 {
  337         uint8_t data;
  338         int ret;
  339 
  340         do {
  341                 ret = cqspi_cmd_read(sc, CMD_READ_STATUS, &data, 1);
  342         } while (data & STATUS_WIP);
  343 
  344         return (0);
  345 }
  346 
  347 static int
  348 cqspi_write_reg(device_t dev, device_t child,
  349     uint8_t opcode, uint8_t *addr, uint32_t len)
  350 {
  351         struct cqspi_softc *sc;
  352         int ret;
  353 
  354         sc = device_get_softc(dev);
  355 
  356         ret = cqspi_cmd_write(sc, opcode, addr, len);
  357 
  358         return (ret);
  359 }
  360 
  361 static int
  362 cqspi_read_reg(device_t dev, device_t child,
  363     uint8_t opcode, uint8_t *addr, uint32_t len)
  364 {
  365         struct cqspi_softc *sc;
  366         int ret;
  367 
  368         sc = device_get_softc(dev);
  369 
  370         ret = cqspi_cmd_read(sc, opcode, addr, len);
  371 
  372         return (ret);
  373 }
  374 
  375 static int
  376 cqspi_wait_idle(struct cqspi_softc *sc)
  377 {
  378         uint32_t reg;
  379 
  380         do {
  381                 reg = READ4(sc, CQSPI_CFG);
  382                 if (reg & CFG_IDLE) {
  383                         break;
  384                 }
  385         } while (1);
  386 
  387         return (0);
  388 }
  389 
  390 static int
  391 cqspi_erase(device_t dev, device_t child, off_t offset)
  392 {
  393         struct cqspi_softc *sc;
  394         int ret;
  395 
  396         sc = device_get_softc(dev);
  397 
  398         cqspi_wait_idle(sc);
  399         cqspi_wait_ready(sc);
  400         ret = cqspi_cmd_write(sc, CMD_WRITE_ENABLE, 0, 0);
  401 
  402         cqspi_wait_idle(sc);
  403         cqspi_wait_ready(sc);
  404         ret = cqspi_cmd_write_addr(sc, CMD_QUAD_SECTOR_ERASE, offset, 4);
  405 
  406         cqspi_wait_idle(sc);
  407 
  408         return (0);
  409 }
  410 
  411 static int
  412 cqspi_write(device_t dev, device_t child, struct bio *bp,
  413     off_t offset, caddr_t data, off_t count)
  414 {
  415         struct cqspi_softc *sc;
  416         uint32_t reg;
  417 
  418         dprintf("%s: offset 0x%llx count %lld bytes\n",
  419             __func__, offset, count);
  420 
  421         sc = device_get_softc(dev);
  422 
  423         cqspi_wait_ready(sc);
  424         reg = cqspi_cmd_write(sc, CMD_WRITE_ENABLE, 0, 0);
  425 
  426         cqspi_wait_idle(sc);
  427         cqspi_wait_ready(sc);
  428         cqspi_wait_idle(sc);
  429 
  430         reg = DMAPER_NUMSGLREQBYTES_4;
  431         reg |= DMAPER_NUMBURSTREQBYTES_4;
  432         WRITE4(sc, CQSPI_DMAPER, reg);
  433 
  434         WRITE4(sc, CQSPI_INDWRWATER, 64);
  435         WRITE4(sc, CQSPI_INDWR, INDRD_IND_OPS_DONE_STATUS);
  436         WRITE4(sc, CQSPI_INDWR, 0);
  437 
  438         WRITE4(sc, CQSPI_INDWRCNT, count);
  439         WRITE4(sc, CQSPI_INDWRSTADDR, offset);
  440 
  441         reg = (0 << DEVWR_DUMMYWRCLKS_S);
  442         reg |= DEVWR_DATA_WIDTH_QUAD;
  443         reg |= DEVWR_ADDR_WIDTH_SINGLE;
  444         reg |= (CMD_QUAD_PAGE_PROGRAM << DEVWR_WROPCODE_S);
  445         WRITE4(sc, CQSPI_DEVWR, reg);
  446 
  447         reg = DEVRD_DATA_WIDTH_QUAD;
  448         reg |= DEVRD_ADDR_WIDTH_SINGLE;
  449         reg |= DEVRD_INST_WIDTH_SINGLE;
  450         WRITE4(sc, CQSPI_DEVRD, reg);
  451 
  452         xdma_enqueue_bio(sc->xchan_tx, &bp,
  453             sc->sram_phys, 4, 4, XDMA_MEM_TO_DEV);
  454         xdma_queue_submit(sc->xchan_tx);
  455 
  456         sc->write_op_done = 0;
  457 
  458         WRITE4(sc, CQSPI_INDWR, INDRD_START);
  459 
  460         while (sc->write_op_done == 0)
  461                 tsleep(&sc->xdma_tx, PCATCH | PZERO, "spi", hz/2);
  462 
  463         cqspi_wait_idle(sc);
  464 
  465         return (0);
  466 }
  467 
  468 static int
  469 cqspi_read(device_t dev, device_t child, struct bio *bp,
  470     off_t offset, caddr_t data, off_t count)
  471 {
  472         struct cqspi_softc *sc;
  473         uint32_t reg;
  474 
  475         sc = device_get_softc(dev);
  476 
  477         dprintf("%s: offset 0x%llx count %lld bytes\n",
  478             __func__, offset, count);
  479 
  480         cqspi_wait_idle(sc);
  481 
  482         reg = DMAPER_NUMSGLREQBYTES_4;
  483         reg |= DMAPER_NUMBURSTREQBYTES_4;
  484         WRITE4(sc, CQSPI_DMAPER, reg);
  485 
  486         WRITE4(sc, CQSPI_INDRDWATER, 64);
  487         WRITE4(sc, CQSPI_INDRD, INDRD_IND_OPS_DONE_STATUS);
  488         WRITE4(sc, CQSPI_INDRD, 0);
  489 
  490         WRITE4(sc, CQSPI_INDRDCNT, count);
  491         WRITE4(sc, CQSPI_INDRDSTADDR, offset);
  492 
  493         reg = (0 << DEVRD_DUMMYRDCLKS_S);
  494         reg |= DEVRD_DATA_WIDTH_QUAD;
  495         reg |= DEVRD_ADDR_WIDTH_SINGLE;
  496         reg |= DEVRD_INST_WIDTH_SINGLE;
  497         reg |= DEVRD_ENMODEBITS;
  498         reg |= (CMD_READ_4B_QUAD_OUTPUT << DEVRD_RDOPCODE_S);
  499         WRITE4(sc, CQSPI_DEVRD, reg);
  500 
  501         WRITE4(sc, CQSPI_MODEBIT, 0xff);
  502         WRITE4(sc, CQSPI_IRQMASK, 0);
  503 
  504         xdma_enqueue_bio(sc->xchan_rx, &bp, sc->sram_phys, 4, 4,
  505             XDMA_DEV_TO_MEM);
  506         xdma_queue_submit(sc->xchan_rx);
  507 
  508         sc->read_op_done = 0;
  509 
  510         WRITE4(sc, CQSPI_INDRD, INDRD_START);
  511 
  512         while (sc->read_op_done == 0)
  513                 tsleep(&sc->xdma_rx, PCATCH | PZERO, "spi", hz/2);
  514 
  515         cqspi_wait_idle(sc);
  516 
  517         return (0);
  518 }
  519 
  520 static int
  521 cqspi_init(struct cqspi_softc *sc)
  522 {
  523         pcell_t dts_value[1];
  524         phandle_t node;
  525         uint32_t reg;
  526         int len;
  527 
  528         device_printf(sc->dev, "Module ID %x\n",
  529             READ4(sc, CQSPI_MODULEID));
  530 
  531         if ((node = ofw_bus_get_node(sc->dev)) == -1) {
  532                 return (ENXIO);
  533         }
  534 
  535         if ((len = OF_getproplen(node, "cdns,fifo-depth")) <= 0) {
  536                 return (ENXIO);
  537         }
  538         OF_getencprop(node, "cdns,fifo-depth", dts_value, len);
  539         sc->fifo_depth = dts_value[0];
  540 
  541         if ((len = OF_getproplen(node, "cdns,fifo-width")) <= 0) {
  542                 return (ENXIO);
  543         }
  544         OF_getencprop(node, "cdns,fifo-width", dts_value, len);
  545         sc->fifo_width = dts_value[0];
  546 
  547         if ((len = OF_getproplen(node, "cdns,trigger-address")) <= 0) {
  548                 return (ENXIO);
  549         }
  550         OF_getencprop(node, "cdns,trigger-address", dts_value, len);
  551         sc->trigger_address = dts_value[0];
  552 
  553         /* Disable controller */
  554         reg = READ4(sc, CQSPI_CFG);
  555         reg &= ~(CFG_EN);
  556         WRITE4(sc, CQSPI_CFG, reg);
  557 
  558         reg = READ4(sc, CQSPI_DEVSZ);
  559         reg &= ~(DEVSZ_NUMADDRBYTES_M);
  560         reg |= ((4 - 1) - DEVSZ_NUMADDRBYTES_S);
  561         WRITE4(sc, CQSPI_DEVSZ, reg);
  562 
  563         WRITE4(sc, CQSPI_SRAMPART, sc->fifo_depth/2);
  564 
  565         /* TODO: calculate baud rate and delay values. */
  566 
  567         reg = READ4(sc, CQSPI_CFG);
  568         /* Configure baud rate */
  569         reg &= ~(CFG_BAUD_M);
  570         reg |= CFG_BAUD12;
  571         reg |= CFG_ENDMA;
  572         WRITE4(sc, CQSPI_CFG, reg);
  573 
  574         reg = (3 << DELAY_NSS_S);
  575         reg |= (3  << DELAY_BTWN_S);
  576         reg |= (1 << DELAY_AFTER_S);
  577         reg |= (1 << DELAY_INIT_S);
  578         WRITE4(sc, CQSPI_DELAY, reg);
  579 
  580         READ4(sc, CQSPI_RDDATACAP);
  581         reg &= ~(RDDATACAP_DELAY_M);
  582         reg |= (1 << RDDATACAP_DELAY_S);
  583         WRITE4(sc, CQSPI_RDDATACAP, reg);
  584 
  585         /* Enable controller */
  586         reg = READ4(sc, CQSPI_CFG);
  587         reg |= (CFG_EN);
  588         WRITE4(sc, CQSPI_CFG, reg);
  589 
  590         return (0);
  591 }
  592 
  593 static int
  594 cqspi_add_devices(device_t dev)
  595 {
  596         phandle_t child, node;
  597         device_t child_dev;
  598         int error;
  599 
  600         node = ofw_bus_get_node(dev);
  601 
  602         for (child = OF_child(node); child != 0; child = OF_peer(child)) {
  603                 child_dev =
  604                     simplebus_add_device(dev, child, 0, NULL, -1, NULL);
  605                 if (child_dev == NULL) {
  606                         return (ENXIO);
  607                 }
  608 
  609                 error = device_probe_and_attach(child_dev);
  610                 if (error != 0) {
  611                         printf("can't probe and attach: %d\n", error);
  612                 }
  613         }
  614 
  615         return (0);
  616 }
  617 
  618 static void
  619 cqspi_delayed_attach(void *arg)
  620 {
  621         struct cqspi_softc *sc;
  622 
  623         sc = arg;
  624 
  625         cqspi_add_devices(sc->dev);
  626         bus_generic_attach(sc->dev);
  627 
  628         config_intrhook_disestablish(&sc->config_intrhook);
  629 }
  630 
  631 static int
  632 cqspi_probe(device_t dev)
  633 {
  634 
  635         if (!ofw_bus_status_okay(dev)) {
  636                 return (ENXIO);
  637         }
  638 
  639         if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
  640                 return (ENXIO);
  641         }
  642 
  643         device_set_desc(dev, "Cadence Quad SPI controller");
  644 
  645         return (0);
  646 }
  647 
  648 static int
  649 cqspi_attach(device_t dev)
  650 {
  651         struct cqspi_softc *sc;
  652         uint32_t caps;
  653         int error;
  654 
  655         sc = device_get_softc(dev);
  656         sc->dev = dev;
  657 
  658         if (bus_alloc_resources(dev, cqspi_spec, sc->res)) {
  659                 device_printf(dev, "could not allocate resources\n");
  660                 return (ENXIO);
  661         }
  662 
  663         /* Memory interface */
  664         sc->bst = rman_get_bustag(sc->res[0]);
  665         sc->bsh = rman_get_bushandle(sc->res[0]);
  666 
  667         sc->sram_phys = rman_get_start(sc->res[1]);
  668 
  669         /* Setup interrupt handlers */
  670         if (bus_setup_intr(sc->dev, sc->res[2], INTR_TYPE_BIO | INTR_MPSAFE,
  671             NULL, cqspi_intr, sc, &sc->ih)) {
  672                 device_printf(sc->dev, "Unable to setup intr\n");
  673                 return (ENXIO);
  674         }
  675 
  676         CQSPI_LOCK_INIT(sc);
  677 
  678         caps = 0;
  679 
  680         /* Get xDMA controller. */
  681         sc->xdma_tx = xdma_ofw_get(sc->dev, "tx");
  682         if (sc->xdma_tx == NULL) {
  683                 device_printf(dev, "Can't find DMA controller.\n");
  684                 return (ENXIO);
  685         }
  686 
  687         sc->xdma_rx = xdma_ofw_get(sc->dev, "rx");
  688         if (sc->xdma_rx == NULL) {
  689                 device_printf(dev, "Can't find DMA controller.\n");
  690                 return (ENXIO);
  691         }
  692 
  693         /* Alloc xDMA virtual channels. */
  694         sc->xchan_tx = xdma_channel_alloc(sc->xdma_tx, caps);
  695         if (sc->xchan_tx == NULL) {
  696                 device_printf(dev, "Can't alloc virtual DMA channel.\n");
  697                 return (ENXIO);
  698         }
  699 
  700         sc->xchan_rx = xdma_channel_alloc(sc->xdma_rx, caps);
  701         if (sc->xchan_rx == NULL) {
  702                 device_printf(dev, "Can't alloc virtual DMA channel.\n");
  703                 return (ENXIO);
  704         }
  705 
  706         /* Setup xDMA interrupt handlers. */
  707         error = xdma_setup_intr(sc->xchan_tx, cqspi_xdma_tx_intr,
  708             sc, &sc->ih_tx);
  709         if (error) {
  710                 device_printf(sc->dev,
  711                     "Can't setup xDMA interrupt handler.\n");
  712                 return (ENXIO);
  713         }
  714 
  715         error = xdma_setup_intr(sc->xchan_rx, cqspi_xdma_rx_intr,
  716             sc, &sc->ih_rx);
  717         if (error) {
  718                 device_printf(sc->dev,
  719                     "Can't setup xDMA interrupt handler.\n");
  720                 return (ENXIO);
  721         }
  722 
  723         xdma_prep_sg(sc->xchan_tx, TX_QUEUE_SIZE, MAXPHYS, 8, 16, 0,
  724             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR);
  725         xdma_prep_sg(sc->xchan_rx, TX_QUEUE_SIZE, MAXPHYS, 8, 16, 0,
  726             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR);
  727 
  728         cqspi_init(sc);
  729 
  730         sc->config_intrhook.ich_func = cqspi_delayed_attach;
  731         sc->config_intrhook.ich_arg = sc;
  732         if (config_intrhook_establish(&sc->config_intrhook) != 0) {
  733                 device_printf(dev, "config_intrhook_establish failed\n");
  734                 return (ENOMEM);
  735         }
  736 
  737         return (0);
  738 }
  739 
  740 static int
  741 cqspi_detach(device_t dev)
  742 {
  743 
  744         return (ENXIO);
  745 }
  746 
  747 static device_method_t cqspi_methods[] = {
  748         /* Device interface */
  749         DEVMETHOD(device_probe,         cqspi_probe),
  750         DEVMETHOD(device_attach,        cqspi_attach),
  751         DEVMETHOD(device_detach,        cqspi_detach),
  752 
  753         /* Quad SPI Flash Interface */
  754         DEVMETHOD(qspi_read_reg,        cqspi_read_reg),
  755         DEVMETHOD(qspi_write_reg,       cqspi_write_reg),
  756         DEVMETHOD(qspi_read,            cqspi_read),
  757         DEVMETHOD(qspi_write,           cqspi_write),
  758         DEVMETHOD(qspi_erase,           cqspi_erase),
  759 
  760         { 0, 0 }
  761 };
  762 
  763 static devclass_t cqspi_devclass;
  764 
  765 DEFINE_CLASS_1(cqspi, cqspi_driver, cqspi_methods,
  766     sizeof(struct cqspi_softc), simplebus_driver);
  767 
  768 DRIVER_MODULE(cqspi, simplebus, cqspi_driver, cqspi_devclass, 0, 0);

Cache object: ae729e1b14183d2711d759183ec00f34


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