static void at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd) { uint32_t cmdr, mr; struct mmc_data *data; sc->curcmd = cmd; data = cmd->data; /* XXX Upper layers don't always set this */ cmd->mrq = sc->req; /* Begin setting up command register. */ cmdr = cmd->opcode; if (sc->host.ios.bus_mode == opendrain) cmdr |= MCI_CMDR_OPDCMD; /* Set up response handling. Allow max timeout for responses. */ if (MMC_RSP(cmd->flags) == MMC_RSP_NONE) cmdr |= MCI_CMDR_RSPTYP_NO; else { cmdr |= MCI_CMDR_MAXLAT; if (cmd->flags & MMC_RSP_136) cmdr |= MCI_CMDR_RSPTYP_136; else cmdr |= MCI_CMDR_RSPTYP_48; } /* * If there is no data transfer, just set up the right interrupt mask * and start the command. * * The interrupt mask needs to be CMDRDY plus all non-data-transfer * errors. It's important to leave the transfer-related errors out, to * avoid spurious timeout or crc errors on a STOP command following a * multiblock read. When a multiblock read is in progress, sending a * STOP in the middle of a block occasionally triggers such errors, but * we're totally disinterested in them because we've already gotten all * the data we wanted without error before sending the STOP command. */ if (data == NULL) { uint32_t ier = MCI_SR_CMDRDY | MCI_SR_RTOE | MCI_SR_RENDE | MCI_SR_RCRCE | MCI_SR_RDIRE | MCI_SR_RINDE; at91_mci_pdc_disable(sc); if (cmd->opcode == MMC_STOP_TRANSMISSION) cmdr |= MCI_CMDR_TRCMD_STOP; /* Ignore response CRC on CMD2 and ACMD41, per standard. */ if (cmd->opcode == MMC_SEND_OP_COND || cmd->opcode == ACMD_SD_SEND_OP_COND) ier &= ~MCI_SR_RCRCE; if (mci_debug) printf("CMDR %x (opcode %d) ARGR %x no data\n", cmdr, cmd->opcode, cmd->arg); WR4(sc, MCI_ARGR, cmd->arg); WR4(sc, MCI_CMDR, cmdr); WR4(sc, MCI_IDR, 0xffffffff); WR4(sc, MCI_IER, ier); return; } /* There is data, set up the transfer-related parts of the command. */ if (data->flags & MMC_DATA_READ) cmdr |= MCI_CMDR_TRDIR; if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) cmdr |= MCI_CMDR_TRCMD_START; if (data->flags & MMC_DATA_STREAM) cmdr |= MCI_CMDR_TRTYP_STREAM; else if (data->flags & MMC_DATA_MULTI) { cmdr |= MCI_CMDR_TRTYP_MULTIPLE; sc->flags |= (data->flags & MMC_DATA_READ) ? CMD_MULTIREAD : CMD_MULTIWRITE; } /* * Disable PDC until we're ready. * * Set block size and turn on PDC mode for dma xfer. * Note that the block size is the smaller of the amount of data to be * transferred, or 512 bytes. The 512 size is fixed by the standard; * smaller blocks are possible, but never larger. */ WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS); mr = RD4(sc,MCI_MR) & ~MCI_MR_BLKLEN; mr |= min(data->len, 512) << 16; WR4(sc, MCI_MR, mr | MCI_MR_PDCMODE|MCI_MR_PDCPADV); /* * Set up DMA. * * Use bounce buffers even if we don't need to byteswap, because doing * multi-block IO with large DMA buffers is way fast (compared to * single-block IO), even after incurring the overhead of also copying * from/to the caller's buffers (which may be in non-contiguous physical * pages). * * In an ideal non-byteswap world we could create a dma tag that allows * for discontiguous segments and do the IO directly from/to the * caller's buffer(s), using ENDRX/ENDTX interrupts to chain the * discontiguous buffers through the PDC. Someday. * * If a read is bigger than 2k, split it in half so that we can start * byte-swapping the first half while the second half is on the wire. * It would be best if we could split it into 8k chunks, but we can't * always keep up with the byte-swapping due to other system activity, * and if an RXBUFF interrupt happens while we're still handling the * byte-swap from the prior buffer (IE, we haven't returned from * handling the prior interrupt yet), then data will get dropped on the * floor and we can't easily recover from that. The right fix for that * would be to have the interrupt handling only keep the DMA flowing and * enqueue filled buffers to be byte-swapped in a non-interrupt context. * Even that won't work on the write side of things though; in that * context we have to have all the data ready to go before starting the * dma. * * XXX what about stream transfers? */ sc->xfer_offset = 0; sc->bbuf_curidx = 0; if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) { uint32_t len; uint32_t remaining = data->len; bus_addr_t paddr; int err; if (remaining > (BBCOUNT*BBSIZE)) panic("IO read size exceeds MAXDATA\n"); if (data->flags & MMC_DATA_READ) { if (remaining > 2048) // XXX len = remaining / 2; else len = remaining; err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0], sc->bbuf_vaddr[0], len, at91_mci_getaddr, &paddr, BUS_DMA_NOWAIT); if (err != 0) panic("IO read dmamap_load failed\n"); bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0], BUS_DMASYNC_PREREAD); WR4(sc, PDC_RPR, paddr); WR4(sc, PDC_RCR, len / 4); sc->bbuf_len[0] = len; remaining -= len; if (remaining == 0) { sc->bbuf_len[1] = 0; } else { len = remaining; err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[1], sc->bbuf_vaddr[1], len, at91_mci_getaddr, &paddr, BUS_DMA_NOWAIT); if (err != 0) panic("IO read dmamap_load failed\n"); bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1], BUS_DMASYNC_PREREAD); WR4(sc, PDC_RNPR, paddr); WR4(sc, PDC_RNCR, len / 4); sc->bbuf_len[1] = len; remaining -= len; } WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN); } else { len = min(BBSIZE, remaining); /* * If this is MCI1 revision 2xx controller, apply * a work-around for the "Data Write Operation and * number of bytes" erratum. */ if ((sc->sc_cap & CAP_MCI1_REV2XX) && len < 12) { len = 12; memset(sc->bbuf_vaddr[0], 0, 12); } at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len); err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0], sc->bbuf_vaddr[0], len, at91_mci_getaddr, &paddr, BUS_DMA_NOWAIT); if (err != 0) panic("IO write dmamap_load failed\n"); bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0], BUS_DMASYNC_PREWRITE); WR4(sc, PDC_TPR,paddr); WR4(sc, PDC_TCR, len / 4); sc->bbuf_len[0] = len; remaining -= len; if (remaining == 0) { sc->bbuf_len[1] = 0; } else { len = remaining; at91_bswap_buf(sc, sc->bbuf_vaddr[1], ((char *)data->data)+BBSIZE, len); err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[1], sc->bbuf_vaddr[1], len, at91_mci_getaddr, &paddr, BUS_DMA_NOWAIT); if (err != 0) panic("IO write dmamap_load failed\n"); bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1], BUS_DMASYNC_PREWRITE); WR4(sc, PDC_TNPR, paddr); WR4(sc, PDC_TNCR, len / 4); sc->bbuf_len[1] = len; remaining -= len; } /* do not enable PDC xfer until CMDRDY asserted */ } data->xfer_len = 0; /* XXX what's this? appears to be unused. */ } if (mci_debug) printf("CMDR %x (opcode %d) ARGR %x with data len %d\n", cmdr, cmd->opcode, cmd->arg, cmd->data->len); WR4(sc, MCI_ARGR, cmd->arg); WR4(sc, MCI_CMDR, cmdr); WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_CMDRDY); }
/** * ti_mmchs_start_cmd - starts the given command * @sc: pointer to the driver context * @cmd: the command to start * * The call tree for this function is * - ti_mmchs_start_cmd * - ti_mmchs_start * - ti_mmchs_request * * LOCKING: * Caller should be holding the OMAP_MMC lock. * * RETURNS: * nothing */ static void ti_mmchs_start_cmd(struct ti_mmchs_softc *sc, struct mmc_command *cmd) { uint32_t cmd_reg, con_reg, ise_reg; struct mmc_data *data; struct mmc_request *req; void *vaddr; bus_addr_t paddr; uint32_t pktsize; sc->curcmd = cmd; data = cmd->data; req = cmd->mrq; /* Ensure the STR and MIT bits are cleared, these are only used for special * command types. */ con_reg = ti_mmchs_read_4(sc, MMCHS_CON); con_reg &= ~(MMCHS_CON_STR | MMCHS_CON_MIT); /* Load the command into bits 29:24 of the CMD register */ cmd_reg = (uint32_t)(cmd->opcode & 0x3F) << 24; /* Set the default set of interrupts */ ise_reg = (MMCHS_STAT_CERR | MMCHS_STAT_CTO | MMCHS_STAT_CC | MMCHS_STAT_CEB); /* Enable CRC checking if requested */ if (cmd->flags & MMC_RSP_CRC) ise_reg |= MMCHS_STAT_CCRC; /* Enable reply index checking if the response supports it */ if (cmd->flags & MMC_RSP_OPCODE) ise_reg |= MMCHS_STAT_CIE; /* Set the expected response length */ if (MMC_RSP(cmd->flags) == MMC_RSP_NONE) { cmd_reg |= MMCHS_CMD_RSP_TYPE_NO; } else { if (cmd->flags & MMC_RSP_136) cmd_reg |= MMCHS_CMD_RSP_TYPE_136; else if (cmd->flags & MMC_RSP_BUSY) cmd_reg |= MMCHS_CMD_RSP_TYPE_48_BSY; else cmd_reg |= MMCHS_CMD_RSP_TYPE_48; /* Enable command index/crc checks if necessary expected */ if (cmd->flags & MMC_RSP_CRC) cmd_reg |= MMCHS_CMD_CCCE; if (cmd->flags & MMC_RSP_OPCODE) cmd_reg |= MMCHS_CMD_CICE; } /* Set the bits for the special commands CMD12 (MMC_STOP_TRANSMISSION) and * CMD52 (SD_IO_RW_DIRECT) */ if (cmd->opcode == MMC_STOP_TRANSMISSION) cmd_reg |= MMCHS_CMD_CMD_TYPE_IO_ABORT; /* Check if there is any data to write */ if (data == NULL) { /* Clear the block count */ ti_mmchs_write_4(sc, MMCHS_BLK, 0); /* The no data case is fairly simple */ ti_mmchs_write_4(sc, MMCHS_CON, con_reg); ti_mmchs_write_4(sc, MMCHS_IE, ise_reg); ti_mmchs_write_4(sc, MMCHS_ISE, ise_reg); ti_mmchs_write_4(sc, MMCHS_ARG, cmd->arg); ti_mmchs_write_4(sc, MMCHS_CMD, cmd_reg); return; } /* Indicate that data is present */ cmd_reg |= MMCHS_CMD_DP | MMCHS_CMD_MSBS | MMCHS_CMD_BCE; /* Indicate a read operation */ if (data->flags & MMC_DATA_READ) cmd_reg |= MMCHS_CMD_DDIR; /* Streaming mode */ if (data->flags & MMC_DATA_STREAM) { con_reg |= MMCHS_CON_STR; } /* Multi-block mode */ if (data->flags & MMC_DATA_MULTI) { cmd_reg |= MMCHS_CMD_MSBS; } /* Enable extra interrupt sources for the transfer */ ise_reg |= (MMCHS_STAT_TC | MMCHS_STAT_DTO | MMCHS_STAT_DEB | MMCHS_STAT_CEB); if (cmd->flags & MMC_RSP_CRC) ise_reg |= MMCHS_STAT_DCRC; /* Enable the DMA transfer bit */ cmd_reg |= MMCHS_CMD_DE; /* Set the block size and block count */ ti_mmchs_write_4(sc, MMCHS_BLK, (1 << 16) | data->len); /* Setup the DMA stuff */ if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) { vaddr = data->data; data->xfer_len = 0; /* Map the buffer buf into bus space using the dmamap map. */ if (bus_dmamap_load(sc->sc_dmatag, sc->sc_dmamap, vaddr, data->len, ti_mmchs_getaddr, &paddr, 0) != 0) { if (req->cmd->flags & STOP_STARTED) req->stop->error = MMC_ERR_NO_MEMORY; else req->cmd->error = MMC_ERR_NO_MEMORY; sc->req = NULL; sc->curcmd = NULL; req->done(req); return; } /* Calculate the packet size, the max packet size is 512 bytes * (or 128 32-bit elements). */ pktsize = min((data->len / 4), (512 / 4)); /* Sync the DMA buffer and setup the DMA controller */ if (data->flags & MMC_DATA_READ) { bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, BUS_DMASYNC_PREREAD); ti_sdma_start_xfer_packet(sc->sc_dmach_rd, sc->sc_data_reg_paddr, paddr, 1, (data->len / 4), pktsize); } else { bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, BUS_DMASYNC_PREWRITE); ti_sdma_start_xfer_packet(sc->sc_dmach_wr, paddr, sc->sc_data_reg_paddr, 1, (data->len / 4), pktsize); } /* Increase the mapped count */ sc->sc_dmamapped++; sc->sc_cmd_data_vaddr = vaddr; sc->sc_cmd_data_len = data->len; } /* Finally kick off the command */ ti_mmchs_write_4(sc, MMCHS_CON, con_reg); ti_mmchs_write_4(sc, MMCHS_IE, ise_reg); ti_mmchs_write_4(sc, MMCHS_ISE, ise_reg); ti_mmchs_write_4(sc, MMCHS_ARG, cmd->arg); ti_mmchs_write_4(sc, MMCHS_CMD, cmd_reg); /* and we're done */ }