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/lpc/lpc_mmc.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) 2011 Jakub Wojciech Klama <jceel@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: releng/10.0/sys/arm/lpc/lpc_mmc.c 239278 2012-08-15 05:37:10Z gonzo $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bio.h>
   33 #include <sys/bus.h>
   34 #include <sys/conf.h>
   35 #include <sys/endian.h>
   36 #include <sys/kernel.h>
   37 #include <sys/kthread.h>
   38 #include <sys/lock.h>
   39 #include <sys/malloc.h>
   40 #include <sys/module.h>
   41 #include <sys/mutex.h>
   42 #include <sys/queue.h>
   43 #include <sys/resource.h>
   44 #include <sys/rman.h>
   45 #include <sys/time.h>
   46 #include <sys/timetc.h>
   47 #include <sys/watchdog.h>
   48 
   49 #include <sys/kdb.h>
   50 
   51 #include <machine/bus.h>
   52 #include <machine/cpu.h>
   53 #include <machine/cpufunc.h>
   54 #include <machine/resource.h>
   55 #include <machine/frame.h>
   56 #include <machine/intr.h>
   57 
   58 #include <dev/ofw/ofw_bus.h>
   59 #include <dev/ofw/ofw_bus_subr.h>
   60 
   61 #include <dev/mmc/bridge.h>
   62 #include <dev/mmc/mmcreg.h>
   63 #include <dev/mmc/mmcbrvar.h>
   64 
   65 #include <arm/lpc/lpcreg.h>
   66 #include <arm/lpc/lpcvar.h>
   67 
   68 #define DEBUG
   69 #undef  DEBUG
   70 
   71 #ifdef DEBUG
   72 #define debugf(fmt, args...) do { printf("%s(): ", __func__);   \
   73     printf(fmt,##args); } while (0)
   74 #else
   75 #define debugf(fmt, args...)
   76 #endif
   77 
   78 struct lpc_mmc_dmamap_arg {
   79         bus_addr_t              lm_dma_busaddr;
   80 };
   81 
   82 struct lpc_mmc_softc {
   83         device_t                lm_dev;
   84         struct mtx              lm_mtx;
   85         struct resource *       lm_mem_res;
   86         struct resource *       lm_irq_res;
   87         bus_space_tag_t         lm_bst;
   88         bus_space_handle_t      lm_bsh;
   89         void *                  lm_intrhand;
   90         struct mmc_host         lm_host;
   91         struct mmc_request *    lm_req;
   92         struct mmc_data *       lm_data;
   93         uint32_t                lm_flags;
   94 #define LPC_SD_FLAGS_IGNORECRC          (1 << 0)
   95         int                     lm_xfer_direction;
   96 #define DIRECTION_READ          0
   97 #define DIRECTION_WRITE         1
   98         int                     lm_xfer_done;
   99         int                     lm_bus_busy;
  100         bus_dma_tag_t           lm_dma_tag;
  101         bus_dmamap_t            lm_dma_map;
  102         bus_addr_t              lm_buffer_phys;
  103         void *                  lm_buffer;
  104 };
  105 
  106 #define LPC_SD_MAX_BLOCKSIZE    1024
  107 /* XXX */
  108 #define LPC_MMC_DMACH_READ      1
  109 #define LPC_MMC_DMACH_WRITE     0
  110 
  111 
  112 static int lpc_mmc_probe(device_t);
  113 static int lpc_mmc_attach(device_t);
  114 static int lpc_mmc_detach(device_t);
  115 static void lpc_mmc_intr(void *);
  116 
  117 static void lpc_mmc_cmd(struct lpc_mmc_softc *, struct mmc_command *);
  118 static void lpc_mmc_setup_xfer(struct lpc_mmc_softc *, struct mmc_data *);
  119 
  120 static int lpc_mmc_update_ios(device_t, device_t);
  121 static int lpc_mmc_request(device_t, device_t, struct mmc_request *);
  122 static int lpc_mmc_get_ro(device_t, device_t);
  123 static int lpc_mmc_acquire_host(device_t, device_t);
  124 static int lpc_mmc_release_host(device_t, device_t);
  125 
  126 static void lpc_mmc_dma_rxfinish(void *);
  127 static void lpc_mmc_dma_rxerror(void *);
  128 static void lpc_mmc_dma_txfinish(void *);
  129 static void lpc_mmc_dma_txerror(void *);
  130 
  131 static void lpc_mmc_dmamap_cb(void *, bus_dma_segment_t *, int, int);
  132 
  133 #define lpc_mmc_lock(_sc)                                               \
  134     mtx_lock(&_sc->lm_mtx);
  135 #define lpc_mmc_unlock(_sc)                                             \
  136     mtx_unlock(&_sc->lm_mtx);
  137 #define lpc_mmc_read_4(_sc, _reg)                                       \
  138     bus_space_read_4(_sc->lm_bst, _sc->lm_bsh, _reg)
  139 #define lpc_mmc_write_4(_sc, _reg, _value)                              \
  140     bus_space_write_4(_sc->lm_bst, _sc->lm_bsh, _reg, _value)
  141 
  142 static struct lpc_dmac_channel_config lpc_mmc_dma_rxconf = {
  143         .ldc_fcntl = LPC_DMAC_FLOW_D_P2M,
  144         .ldc_src_periph = LPC_DMAC_SD_ID,
  145         .ldc_src_width = LPC_DMAC_CH_CONTROL_WIDTH_4,
  146         .ldc_src_incr = 0,
  147         .ldc_src_burst = LPC_DMAC_CH_CONTROL_BURST_8,
  148         .ldc_dst_periph = LPC_DMAC_SD_ID,
  149         .ldc_dst_width = LPC_DMAC_CH_CONTROL_WIDTH_4,
  150         .ldc_dst_incr = 1,
  151         .ldc_dst_burst = LPC_DMAC_CH_CONTROL_BURST_8,
  152         .ldc_success_handler = lpc_mmc_dma_rxfinish,
  153         .ldc_error_handler = lpc_mmc_dma_rxerror,
  154 };
  155 
  156 static struct lpc_dmac_channel_config lpc_mmc_dma_txconf = {
  157         .ldc_fcntl = LPC_DMAC_FLOW_P_M2P,
  158         .ldc_src_periph = LPC_DMAC_SD_ID,
  159         .ldc_src_width = LPC_DMAC_CH_CONTROL_WIDTH_4,
  160         .ldc_src_incr = 1,
  161         .ldc_src_burst = LPC_DMAC_CH_CONTROL_BURST_8,
  162         .ldc_dst_periph = LPC_DMAC_SD_ID,
  163         .ldc_dst_width = LPC_DMAC_CH_CONTROL_WIDTH_4,
  164         .ldc_dst_incr = 0,
  165         .ldc_dst_burst = LPC_DMAC_CH_CONTROL_BURST_8,
  166         .ldc_success_handler = lpc_mmc_dma_txfinish,
  167         .ldc_error_handler = lpc_mmc_dma_txerror,
  168 };
  169 
  170 static int
  171 lpc_mmc_probe(device_t dev)
  172 {
  173         if (!ofw_bus_is_compatible(dev, "lpc,mmc"))
  174                 return (ENXIO);
  175 
  176         device_set_desc(dev, "LPC32x0 MMC/SD controller");
  177         return (BUS_PROBE_DEFAULT);
  178 }
  179 
  180 static int
  181 lpc_mmc_attach(device_t dev)
  182 {
  183         struct lpc_mmc_softc *sc = device_get_softc(dev);
  184         struct lpc_mmc_dmamap_arg ctx;
  185         device_t child;
  186         int rid, err;
  187 
  188         sc->lm_dev = dev;
  189         sc->lm_req = NULL;
  190 
  191         mtx_init(&sc->lm_mtx, "lpcmmc", "mmc", MTX_DEF);
  192 
  193         rid = 0;
  194         sc->lm_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  195             RF_ACTIVE);
  196         if (!sc->lm_mem_res) {
  197                 device_printf(dev, "cannot allocate memory window\n");
  198                 return (ENXIO);
  199         }
  200 
  201         sc->lm_bst = rman_get_bustag(sc->lm_mem_res);
  202         sc->lm_bsh = rman_get_bushandle(sc->lm_mem_res);
  203 
  204         debugf("virtual register space: 0x%08lx\n", sc->lm_bsh);
  205 
  206         rid = 0;
  207         sc->lm_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  208             RF_ACTIVE);
  209         if (!sc->lm_irq_res) {
  210                 device_printf(dev, "cannot allocate interrupt\n");
  211                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lm_mem_res);
  212                 return (ENXIO);
  213         }
  214 
  215         if (bus_setup_intr(dev, sc->lm_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
  216             NULL, lpc_mmc_intr, sc, &sc->lm_intrhand))
  217         {
  218                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lm_mem_res);
  219                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lm_irq_res);
  220                 device_printf(dev, "cannot setup interrupt handler\n");
  221                 return (ENXIO);
  222         }
  223 
  224         sc->lm_host.f_min = 312500;
  225         sc->lm_host.f_max = 2500000;
  226         sc->lm_host.host_ocr = MMC_OCR_300_310 | MMC_OCR_310_320 |
  227             MMC_OCR_320_330 | MMC_OCR_330_340;
  228 #if 0
  229         sc->lm_host.caps = MMC_CAP_4_BIT_DATA;
  230 #endif
  231 
  232         lpc_pwr_write(dev, LPC_CLKPWR_MS_CTRL,
  233             LPC_CLKPWR_MS_CTRL_CLOCK_EN | LPC_CLKPWR_MS_CTRL_SD_CLOCK | 1);
  234         lpc_mmc_write_4(sc, LPC_SD_POWER, LPC_SD_POWER_CTRL_ON);
  235 
  236         device_set_ivars(dev, &sc->lm_host);
  237 
  238         child = device_add_child(dev, "mmc", -1);
  239         if (!child) {
  240                 device_printf(dev, "attaching MMC bus failed!\n");
  241                 bus_teardown_intr(dev, sc->lm_irq_res, sc->lm_intrhand);
  242                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lm_mem_res);
  243                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lm_irq_res);
  244                 return (ENXIO);
  245         }
  246 
  247         /* Alloc DMA memory */
  248         err = bus_dma_tag_create(
  249             bus_get_dma_tag(sc->lm_dev),
  250             4, 0,                       /* alignment, boundary */
  251             BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
  252             BUS_SPACE_MAXADDR,          /* highaddr */
  253             NULL, NULL,                 /* filter, filterarg */
  254             LPC_SD_MAX_BLOCKSIZE, 1,    /* maxsize, nsegments */
  255             LPC_SD_MAX_BLOCKSIZE, 0,    /* maxsegsize, flags */
  256             NULL, NULL,                 /* lockfunc, lockarg */
  257             &sc->lm_dma_tag);
  258 
  259         err = bus_dmamem_alloc(sc->lm_dma_tag, (void **)&sc->lm_buffer,
  260             0, &sc->lm_dma_map);
  261         if (err) {
  262                 device_printf(dev, "cannot allocate framebuffer\n");
  263                 goto fail;
  264         }
  265 
  266         err = bus_dmamap_load(sc->lm_dma_tag, sc->lm_dma_map, sc->lm_buffer,
  267             LPC_SD_MAX_BLOCKSIZE, lpc_mmc_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
  268         if (err) {
  269                 device_printf(dev, "cannot load DMA map\n");
  270                 goto fail;
  271         }
  272 
  273         sc->lm_buffer_phys = ctx.lm_dma_busaddr;
  274 
  275         lpc_mmc_dma_rxconf.ldc_handler_arg = (void *)sc;
  276         err = lpc_dmac_config_channel(dev, LPC_MMC_DMACH_READ, &lpc_mmc_dma_rxconf);
  277         if (err) {
  278                 device_printf(dev, "cannot allocate RX DMA channel\n");
  279                 goto fail;
  280         }
  281 
  282 
  283         lpc_mmc_dma_txconf.ldc_handler_arg = (void *)sc;
  284         err = lpc_dmac_config_channel(dev, LPC_MMC_DMACH_WRITE, &lpc_mmc_dma_txconf);   
  285         if (err) {
  286                 device_printf(dev, "cannot allocate TX DMA channel\n");
  287                 goto fail;
  288         }
  289 
  290         bus_generic_probe(dev);
  291         bus_generic_attach(dev);
  292 
  293         return (0);
  294 
  295 fail:
  296         if (sc->lm_intrhand)
  297                 bus_teardown_intr(dev, sc->lm_irq_res, sc->lm_intrhand);
  298         if (sc->lm_irq_res)
  299                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lm_irq_res);
  300         if (sc->lm_mem_res)
  301                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lm_mem_res);
  302         return (err);
  303 }
  304 
  305 static int
  306 lpc_mmc_detach(device_t dev)
  307 {
  308         return (EBUSY);
  309 }
  310 
  311 static void
  312 lpc_mmc_intr(void *arg)
  313 {
  314         struct lpc_mmc_softc *sc = (struct lpc_mmc_softc *)arg;
  315         struct mmc_command *cmd;
  316         uint32_t status;
  317 
  318         status = lpc_mmc_read_4(sc, LPC_SD_STATUS);
  319 
  320         debugf("interrupt: 0x%08x\n", status);
  321 
  322         if (status & LPC_SD_STATUS_CMDCRCFAIL) {
  323                 cmd = sc->lm_req->cmd;
  324                 cmd->error = sc->lm_flags & LPC_SD_FLAGS_IGNORECRC
  325                     ? MMC_ERR_NONE : MMC_ERR_BADCRC;
  326                 cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
  327                 sc->lm_req->done(sc->lm_req);
  328                 sc->lm_req = NULL;
  329                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDCRCFAIL);    
  330         }
  331 
  332         if (status & LPC_SD_STATUS_CMDACTIVE)
  333         {
  334                 debugf("command active\n");
  335                 cmd = sc->lm_req->cmd;
  336                 cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
  337                 sc->lm_req->done(sc->lm_req);
  338                 sc->lm_req = NULL;
  339         }
  340         
  341         if (status & LPC_SD_STATUS_DATATIMEOUT) {
  342                 device_printf(sc->lm_dev, "data timeout\n");
  343                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATATIMEOUT);
  344         }
  345 
  346         if (status & LPC_SD_STATUS_TXUNDERRUN) {
  347                 device_printf(sc->lm_dev, "TX underrun\n");
  348                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_TXUNDERRUN);
  349         }
  350         
  351         if (status & LPC_SD_STATUS_CMDRESPEND) {
  352                 debugf("command response\n");
  353                 cmd = sc->lm_req->cmd;
  354                 
  355                 if (cmd->flags & MMC_RSP_136) {
  356                         cmd->resp[3] = lpc_mmc_read_4(sc, LPC_SD_RESP3);
  357                         cmd->resp[2] = lpc_mmc_read_4(sc, LPC_SD_RESP2);
  358                         cmd->resp[1] = lpc_mmc_read_4(sc, LPC_SD_RESP1);
  359                 }
  360 
  361                 cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
  362                 cmd->error = MMC_ERR_NONE;
  363         
  364                 if (cmd->data && (cmd->data->flags & MMC_DATA_WRITE))
  365                         lpc_mmc_setup_xfer(sc, sc->lm_req->cmd->data);
  366 
  367                 if (!cmd->data) {       
  368                         sc->lm_req->done(sc->lm_req);
  369                         sc->lm_req = NULL;
  370                 }
  371 
  372                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDRESPEND);
  373         }
  374 
  375         if (status & LPC_SD_STATUS_CMDSENT) {
  376                 debugf("command sent\n");
  377                 cmd = sc->lm_req->cmd;
  378                 cmd->error = MMC_ERR_NONE;
  379                 sc->lm_req->done(sc->lm_req);
  380                 sc->lm_req = NULL;
  381                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDSENT);
  382         }
  383         
  384         if (status & LPC_SD_STATUS_DATAEND) {
  385                 if (sc->lm_xfer_direction == DIRECTION_READ)
  386                         lpc_dmac_start_burst(sc->lm_dev, LPC_DMAC_SD_ID);
  387 
  388                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATAEND);
  389         }
  390 
  391         if (status & LPC_SD_STATUS_CMDTIMEOUT) {
  392                 device_printf(sc->lm_dev, "command response timeout\n");
  393                 cmd = sc->lm_req->cmd;
  394                 cmd->error = MMC_ERR_TIMEOUT;
  395                 sc->lm_req->done(sc->lm_req);
  396                 sc->lm_req = NULL;
  397                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDTIMEOUT);
  398                 return;
  399         }
  400 
  401         if (status & LPC_SD_STATUS_STARTBITERR) {
  402                 device_printf(sc->lm_dev, "start bit error\n");
  403                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_STARTBITERR);
  404         }
  405 
  406         if (status & LPC_SD_STATUS_DATACRCFAIL) {               
  407                 device_printf(sc->lm_dev, "data CRC error\n");
  408                 debugf("data buffer: %p\n", sc->lm_buffer);
  409                 cmd = sc->lm_req->cmd;
  410                 cmd->error = MMC_ERR_BADCRC;
  411                 sc->lm_req->done(sc->lm_req);
  412                 sc->lm_req = NULL;
  413 
  414                 if (sc->lm_xfer_direction == DIRECTION_READ)
  415                         lpc_dmac_start_burst(sc->lm_dev, LPC_DMAC_SD_ID);
  416 
  417                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATACRCFAIL);
  418         }
  419 
  420         if (status & LPC_SD_STATUS_DATABLOCKEND) {
  421                 debugf("data block end\n");
  422                 if (sc->lm_xfer_direction == DIRECTION_READ)
  423                         memcpy(sc->lm_data->data, sc->lm_buffer, sc->lm_data->len);
  424 
  425                 if (sc->lm_xfer_direction == DIRECTION_WRITE) {
  426                         lpc_dmac_disable_channel(sc->lm_dev, LPC_MMC_DMACH_WRITE);
  427                         lpc_mmc_write_4(sc, LPC_SD_DATACTRL, 0);
  428                 }
  429         
  430                 sc->lm_req->done(sc->lm_req);
  431                 sc->lm_req = NULL;
  432                 lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATABLOCKEND);
  433         }
  434 
  435         debugf("done\n");
  436 }
  437 
  438 static int
  439 lpc_mmc_request(device_t bus, device_t child, struct mmc_request *req)
  440 {
  441         struct lpc_mmc_softc *sc = device_get_softc(bus);
  442 
  443         debugf("request: %p\n", req);
  444 
  445         lpc_mmc_lock(sc);
  446         if (sc->lm_req)
  447                 return (EBUSY);
  448 
  449         sc->lm_req = req;
  450 
  451         if (req->cmd->data && req->cmd->data->flags & MMC_DATA_WRITE) {
  452                 memcpy(sc->lm_buffer, req->cmd->data->data, req->cmd->data->len);
  453                 lpc_mmc_cmd(sc, req->cmd);
  454                 lpc_mmc_unlock(sc);
  455                 return (0);
  456         }
  457 
  458         if (req->cmd->data)
  459                 lpc_mmc_setup_xfer(sc, req->cmd->data);
  460 
  461         lpc_mmc_cmd(sc, req->cmd);
  462         lpc_mmc_unlock(sc);
  463 
  464         return (0);
  465 }
  466 
  467 static void
  468 lpc_mmc_cmd(struct lpc_mmc_softc *sc, struct mmc_command *cmd)
  469 {
  470         uint32_t cmdreg = 0;
  471 
  472         debugf("cmd: %d arg: 0x%08x\n", cmd->opcode, cmd->arg);
  473 
  474         if (lpc_mmc_read_4(sc, LPC_SD_COMMAND) & LPC_SD_COMMAND_ENABLE) {
  475                 lpc_mmc_write_4(sc, LPC_SD_COMMAND, 0);
  476                 DELAY(1000);
  477         }
  478 
  479         sc->lm_flags &= ~LPC_SD_FLAGS_IGNORECRC;
  480 
  481         if (cmd->flags & MMC_RSP_PRESENT)
  482                 cmdreg |= LPC_SD_COMMAND_RESPONSE;
  483 
  484         if (MMC_RSP(cmd->flags) == MMC_RSP_R2)
  485                 cmdreg |= LPC_SD_COMMAND_LONGRSP;
  486 
  487         if (MMC_RSP(cmd->flags) == MMC_RSP_R3)
  488                 sc->lm_flags |= LPC_SD_FLAGS_IGNORECRC;
  489 
  490         cmdreg |= LPC_SD_COMMAND_ENABLE;
  491         cmdreg |= (cmd->opcode & LPC_SD_COMMAND_CMDINDEXMASK);
  492 
  493         lpc_mmc_write_4(sc, LPC_SD_MASK0, 0xffffffff);
  494         lpc_mmc_write_4(sc, LPC_SD_MASK1, 0xffffffff);
  495         lpc_mmc_write_4(sc, LPC_SD_ARGUMENT, cmd->arg);
  496         lpc_mmc_write_4(sc, LPC_SD_COMMAND, cmdreg);
  497 }
  498 
  499 static void
  500 lpc_mmc_setup_xfer(struct lpc_mmc_softc *sc, struct mmc_data *data)
  501 {
  502         uint32_t datactrl = 0;
  503         int data_words = data->len / 4;
  504 
  505         sc->lm_data = data;
  506         sc->lm_xfer_done = 0;
  507 
  508         debugf("data: %p, len: %d, %s\n", data,
  509             data->len, (data->flags & MMC_DATA_READ) ? "read" : "write");
  510 
  511         if (data->flags & MMC_DATA_READ) {
  512                 sc->lm_xfer_direction = DIRECTION_READ;
  513                 lpc_dmac_setup_transfer(sc->lm_dev, LPC_MMC_DMACH_READ,
  514                     LPC_SD_BASE + LPC_SD_FIFO, sc->lm_buffer_phys,
  515                     data_words, 0);
  516         }
  517 
  518         if (data->flags & MMC_DATA_WRITE) {
  519                 sc->lm_xfer_direction = DIRECTION_WRITE;
  520                 lpc_dmac_setup_transfer(sc->lm_dev, LPC_MMC_DMACH_WRITE,
  521                     sc->lm_buffer_phys, LPC_SD_BASE + LPC_SD_FIFO,
  522                     data_words, 0);
  523         }
  524 
  525         datactrl |= (sc->lm_xfer_direction 
  526             ? LPC_SD_DATACTRL_WRITE 
  527             : LPC_SD_DATACTRL_READ);
  528 
  529         datactrl |= LPC_SD_DATACTRL_DMAENABLE | LPC_SD_DATACTRL_ENABLE;
  530         datactrl |= (ffs(data->len) - 1) << 4;
  531 
  532         debugf("datactrl: 0x%08x\n", datactrl);
  533 
  534         lpc_mmc_write_4(sc, LPC_SD_DATATIMER, 0xFFFF0000);
  535         lpc_mmc_write_4(sc, LPC_SD_DATALENGTH, data->len);
  536         lpc_mmc_write_4(sc, LPC_SD_DATACTRL, datactrl);
  537 }
  538 
  539 static int
  540 lpc_mmc_read_ivar(device_t bus, device_t child, int which, 
  541     uintptr_t *result)
  542 {
  543         struct lpc_mmc_softc *sc = device_get_softc(bus);
  544 
  545         switch (which) {
  546         default:
  547                 return (EINVAL);
  548         case MMCBR_IVAR_BUS_MODE:
  549                 *(int *)result = sc->lm_host.ios.bus_mode;
  550                 break;
  551         case MMCBR_IVAR_BUS_WIDTH:
  552                 *(int *)result = sc->lm_host.ios.bus_width;
  553                 break;
  554         case MMCBR_IVAR_CHIP_SELECT:
  555                 *(int *)result = sc->lm_host.ios.chip_select;
  556                 break;
  557         case MMCBR_IVAR_CLOCK:
  558                 *(int *)result = sc->lm_host.ios.clock;
  559                 break;
  560         case MMCBR_IVAR_F_MIN:
  561                 *(int *)result = sc->lm_host.f_min;
  562                 break;
  563         case MMCBR_IVAR_F_MAX:
  564                 *(int *)result = sc->lm_host.f_max;
  565                 break;
  566         case MMCBR_IVAR_HOST_OCR:
  567                 *(int *)result = sc->lm_host.host_ocr;
  568                 break;
  569         case MMCBR_IVAR_MODE:
  570                 *(int *)result = sc->lm_host.mode;
  571                 break;
  572         case MMCBR_IVAR_OCR:
  573                 *(int *)result = sc->lm_host.ocr;
  574                 break;
  575         case MMCBR_IVAR_POWER_MODE:
  576                 *(int *)result = sc->lm_host.ios.power_mode;
  577                 break;
  578         case MMCBR_IVAR_VDD:
  579                 *(int *)result = sc->lm_host.ios.vdd;
  580                 break;
  581         case MMCBR_IVAR_CAPS:
  582                 *(int *)result = sc->lm_host.caps;
  583                 break;
  584         case MMCBR_IVAR_MAX_DATA:
  585                 *(int *)result = 1;
  586                 break;
  587         }
  588 
  589         return (0);
  590 }
  591 
  592 static int
  593 lpc_mmc_write_ivar(device_t bus, device_t child, int which,
  594     uintptr_t value)
  595 {
  596         struct lpc_mmc_softc *sc = device_get_softc(bus);
  597 
  598         switch (which) {
  599         default:
  600                 return (EINVAL);
  601         case MMCBR_IVAR_BUS_MODE:
  602                 sc->lm_host.ios.bus_mode = value;
  603                 break;
  604         case MMCBR_IVAR_BUS_WIDTH:
  605                 sc->lm_host.ios.bus_width = value;
  606                 break;
  607         case MMCBR_IVAR_CHIP_SELECT:
  608                 sc->lm_host.ios.chip_select = value;
  609                 break;
  610         case MMCBR_IVAR_CLOCK:
  611                 sc->lm_host.ios.clock = value;
  612                 break;
  613         case MMCBR_IVAR_MODE:
  614                 sc->lm_host.mode = value;
  615                 break;
  616         case MMCBR_IVAR_OCR:
  617                 sc->lm_host.ocr = value;
  618                 break;
  619         case MMCBR_IVAR_POWER_MODE:
  620                 sc->lm_host.ios.power_mode = value;
  621                 break;
  622         case MMCBR_IVAR_VDD:
  623                 sc->lm_host.ios.vdd = value;
  624                 break;
  625         /* These are read-only */
  626         case MMCBR_IVAR_CAPS:
  627         case MMCBR_IVAR_HOST_OCR:
  628         case MMCBR_IVAR_F_MIN:
  629         case MMCBR_IVAR_F_MAX:
  630         case MMCBR_IVAR_MAX_DATA:
  631                 return (EINVAL);
  632         }
  633         return (0);
  634 }
  635 
  636 static int
  637 lpc_mmc_update_ios(device_t bus, device_t child)
  638 {
  639         struct lpc_mmc_softc *sc = device_get_softc(bus);
  640         struct mmc_ios *ios = &sc->lm_host.ios;
  641         uint32_t clkdiv = 0, pwr = 0;
  642 
  643         if (ios->bus_width == bus_width_4)
  644                 clkdiv |= LPC_SD_CLOCK_WIDEBUS;
  645 
  646         /* Calculate clock divider */
  647         clkdiv = (LPC_SD_CLK / (2 * ios->clock)) - 1;
  648 
  649         /* Clock rate should not exceed rate requested in ios */
  650         if ((LPC_SD_CLK / (2 * (clkdiv + 1))) > ios->clock)
  651                 clkdiv++;
  652 
  653         debugf("clock: %dHz, clkdiv: %d\n", ios->clock, clkdiv);
  654 
  655         if (ios->bus_width == bus_width_4) {
  656                 debugf("using wide bus mode\n");
  657                 clkdiv |= LPC_SD_CLOCK_WIDEBUS;
  658         }
  659 
  660         lpc_mmc_write_4(sc, LPC_SD_CLOCK, clkdiv | LPC_SD_CLOCK_ENABLE);
  661 
  662         switch (ios->power_mode) {
  663         case power_off:
  664                 pwr |= LPC_SD_POWER_CTRL_OFF;
  665                 break;
  666         case power_up:
  667                 pwr |= LPC_SD_POWER_CTRL_UP;
  668                 break;
  669         case power_on:
  670                 pwr |= LPC_SD_POWER_CTRL_ON;
  671                 break;
  672         }
  673 
  674         if (ios->bus_mode == opendrain)
  675                 pwr |= LPC_SD_POWER_OPENDRAIN;
  676 
  677         lpc_mmc_write_4(sc, LPC_SD_POWER, pwr);
  678 
  679         return (0);
  680 }
  681 
  682 static int
  683 lpc_mmc_get_ro(device_t bus, device_t child)
  684 {
  685 
  686         return (0);
  687 }
  688 
  689 static int
  690 lpc_mmc_acquire_host(device_t bus, device_t child)
  691 {
  692         struct lpc_mmc_softc *sc = device_get_softc(bus);
  693         int error = 0;
  694 
  695         lpc_mmc_lock(sc);
  696         while (sc->lm_bus_busy)
  697                 error = mtx_sleep(sc, &sc->lm_mtx, PZERO, "mmcah", 0);
  698 
  699         sc->lm_bus_busy++;
  700         lpc_mmc_unlock(sc);
  701         return (error);
  702 }
  703 
  704 static int
  705 lpc_mmc_release_host(device_t bus, device_t child)
  706 {
  707         struct lpc_mmc_softc *sc = device_get_softc(bus);
  708 
  709         lpc_mmc_lock(sc);
  710         sc->lm_bus_busy--;
  711         wakeup(sc);
  712         lpc_mmc_unlock(sc);
  713         return (0);
  714 }
  715 
  716 static void lpc_mmc_dma_rxfinish(void *arg)
  717 {
  718 }
  719 
  720 static void lpc_mmc_dma_rxerror(void *arg)
  721 {
  722         struct lpc_mmc_softc *sc = (struct lpc_mmc_softc *)arg;
  723         device_printf(sc->lm_dev, "DMA RX error\n");
  724 }
  725 
  726 static void lpc_mmc_dma_txfinish(void *arg)
  727 {
  728 }
  729 
  730 static void lpc_mmc_dma_txerror(void *arg)
  731 {
  732         struct lpc_mmc_softc *sc = (struct lpc_mmc_softc *)arg;
  733         device_printf(sc->lm_dev, "DMA TX error\n");
  734 }
  735 
  736 static void
  737 lpc_mmc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
  738 {
  739         struct lpc_mmc_dmamap_arg *ctx;
  740 
  741         if (err)
  742                 return;
  743 
  744         ctx = (struct lpc_mmc_dmamap_arg *)arg;
  745         ctx->lm_dma_busaddr = segs[0].ds_addr;
  746 }
  747 
  748 static device_method_t lpc_mmc_methods[] = {
  749         /* Device interface */
  750         DEVMETHOD(device_probe,         lpc_mmc_probe),
  751         DEVMETHOD(device_attach,        lpc_mmc_attach),
  752         DEVMETHOD(device_detach,        lpc_mmc_detach),
  753 
  754         /* Bus interface */
  755         DEVMETHOD(bus_read_ivar,        lpc_mmc_read_ivar),
  756         DEVMETHOD(bus_write_ivar,       lpc_mmc_write_ivar),
  757         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  758 
  759         /* MMC bridge interface */
  760         DEVMETHOD(mmcbr_update_ios,     lpc_mmc_update_ios),
  761         DEVMETHOD(mmcbr_request,        lpc_mmc_request),
  762         DEVMETHOD(mmcbr_get_ro,         lpc_mmc_get_ro),
  763         DEVMETHOD(mmcbr_acquire_host,   lpc_mmc_acquire_host),
  764         DEVMETHOD(mmcbr_release_host,   lpc_mmc_release_host),
  765 
  766         { 0, 0 }
  767 };
  768 
  769 static devclass_t lpc_mmc_devclass;
  770 
  771 static driver_t lpc_mmc_driver = {
  772         "lpcmmc",
  773         lpc_mmc_methods,
  774         sizeof(struct lpc_mmc_softc),
  775 };
  776 
  777 DRIVER_MODULE(lpcmmc, simplebus, lpc_mmc_driver, lpc_mmc_devclass, 0, 0);

Cache object: 66a7de5d1093a1c2a9989fa633c847de


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