Beispiel #1
0
static void
goldfish_mmc_start_command(struct goldfish_mmc_host *host,
			   struct mmc_command *cmd)
{
	u32 cmdreg;
	u32 resptype;
	u32 cmdtype;

	host->cmd = cmd;

	resptype = 0;
	cmdtype = 0;

	/* Our hardware needs to know exact type */
	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		break;
	case MMC_RSP_R1:
	case MMC_RSP_R1B:
		/* resp 1, 1b, 6, 7 */
		resptype = 1;
		break;
	case MMC_RSP_R2:
		resptype = 2;
		break;
	case MMC_RSP_R3:
		resptype = 3;
		break;
	default:
		dev_err(mmc_dev(host->mmc), "Invalid response type: %04x\n",
			mmc_resp_type(cmd));
		break;
	}

	if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) {
		cmdtype = OMAP_MMC_CMDTYPE_ADTC;
	} else if (mmc_cmd_type(cmd) == MMC_CMD_BC) {
		cmdtype = OMAP_MMC_CMDTYPE_BC;
	} else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) {
		cmdtype = OMAP_MMC_CMDTYPE_BCR;
	} else {
		cmdtype = OMAP_MMC_CMDTYPE_AC;
	}

	cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);

	if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
		cmdreg |= 1 << 6;

	if (cmd->flags & MMC_RSP_BUSY)
		cmdreg |= 1 << 11;

	if (host->data && !(host->data->flags & MMC_DATA_WRITE))
		cmdreg |= 1 << 15;

	GOLDFISH_MMC_WRITE(host, MMC_ARG, cmd->arg);
	GOLDFISH_MMC_WRITE(host, MMC_CMD, cmdreg);
}
Beispiel #2
0
static void nuc970_emmc_send_stop(struct nuc970_emmc_host *host, struct mmc_command *cmd)
{
    unsigned int csr;
    unsigned int block_length;
    unsigned int blocks;

    host->cmd = cmd;
    emmc_host = host;
    emmc_state = 0;
    emmc_state_xfer = 0;

    if (nuc970_emmc_read(REG_NAND_FMICSR) != FMICSR_EMMCEN)
        nuc970_emmc_write(REG_NAND_FMICSR, FMICSR_EMMCEN);

    csr = nuc970_emmc_read(REG_EMMCCSR) & 0xff00c080;

    csr = csr | (cmd->opcode << 8) | EMMCCSR_CO_EN;   // set command code and enable command out
    emmc_event |= EMMC_EVENT_CMD_OUT;

    if (host->bus_mode == MMC_BUS_WIDTH_4)
        csr |= EMMCCSR_DBW;

    if (mmc_resp_type(cmd) != MMC_RSP_NONE)
    {
    /* if a response is expected then allow maximum response latancy */

        /* set 136 bit response for R2, 48 bit response otherwise */
        if (mmc_resp_type(cmd) == MMC_RSP_R2)
        {
            csr |= EMMCCSR_R2_EN;
            emmc_event |= EMMC_EVENT_RSP2_IN;
        }
        else
        {
            csr |= EMMCCSR_RI_EN;
            emmc_event |= EMMC_EVENT_RSP_IN;
        }
        nuc970_emmc_write(REG_EMMCISR, EMMCISR_RITO_IF);
        emmc_ri_timeout = 0;
        nuc970_emmc_write(REG_EMMCTMOUT, 0xffff);
    }

    nuc970_emmc_write(REG_EMMCIER, nuc970_emmc_read(REG_EMMCIER) & ~EMMCIER_BLKD_IE); //disable SD interrupt
    block_length = 0;
    blocks = 0;

    nuc970_emmc_write(REG_EMMCARG, cmd->arg);
    nuc970_emmc_write(REG_EMMCCSR, csr);
    emmc_send_cmd = 1;
    wake_up_interruptible(&emmc_event_wq);

    mmc_request_done(host->mmc, host->request);
}
Beispiel #3
0
static int usdhi6_cmd_flags(struct usdhi6_host *host)
{
	struct mmc_request *mrq = host->mrq;
	struct mmc_command *cmd = mrq->cmd;
	u16 opc = cmd->opcode;

	if (host->app_cmd) {
		host->app_cmd = false;
		opc |= USDHI6_SD_CMD_APP;
	}

	if (mrq->data) {
		opc |= USDHI6_SD_CMD_DATA;

		if (mrq->data->flags & MMC_DATA_READ)
			opc |= USDHI6_SD_CMD_READ;

		if (cmd->opcode == MMC_READ_MULTIPLE_BLOCK ||
		    cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK ||
		    (cmd->opcode == SD_IO_RW_EXTENDED &&
		     mrq->data->blocks > 1)) {
			opc |= USDHI6_SD_CMD_MULTI;
			if (!mrq->stop)
				opc |= USDHI6_SD_CMD_CMD12_AUTO_OFF;
		}

		switch (mmc_resp_type(cmd)) {
		case MMC_RSP_NONE:
			opc |= USDHI6_SD_CMD_MODE_RSP_NONE;
			break;
		case MMC_RSP_R1:
			opc |= USDHI6_SD_CMD_MODE_RSP_R1;
			break;
		case MMC_RSP_R1B:
			opc |= USDHI6_SD_CMD_MODE_RSP_R1B;
			break;
		case MMC_RSP_R2:
			opc |= USDHI6_SD_CMD_MODE_RSP_R2;
			break;
		case MMC_RSP_R3:
			opc |= USDHI6_SD_CMD_MODE_RSP_R3;
			break;
		default:
			dev_warn(mmc_dev(host->mmc),
				 "Unknown response type %d\n",
				 mmc_resp_type(cmd));
			return -EINVAL;
		}
	}

	return opc;
}
Beispiel #4
0
static void hi_mci_cmd_done(struct himci_host *host, unsigned int stat)
{
	unsigned int i;
	struct mmc_command *cmd = host->cmd;

	himci_trace(2, "begin");
	himci_assert(host);
	himci_assert(cmd);

	host->cmd = NULL;

	for (i = 0; i < 4; i++) {
		if (mmc_resp_type(cmd) == MMC_RSP_R2)
			cmd->resp[i] = himci_readl(host->base +
					MCI_RESP3 - i * 0x4);
		else
			cmd->resp[i] = himci_readl(host->base +
					MCI_RESP0 + i * 0x4);
	}

	if (stat & RTO_INT_STATUS) {
		cmd->error = -ETIMEDOUT;
		himci_trace(3, "irq cmd status stat = 0x%x is timeout error!",
				stat);
	} else if (stat & (RCRC_INT_STATUS | RE_INT_STATUS)) {
		cmd->error = -EILSEQ;
		himci_trace(3, "irq cmd status stat = 0x%x is response error!",
				stat);
	}
}
Beispiel #5
0
static int sdhi_boot_request(void __iomem *base, struct mmc_command *cmd)
{
	int err, c = cmd->opcode;

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE: c |= RESP_NONE; break;
	case MMC_RSP_R1:   c |= RESP_R1;   break;
	case MMC_RSP_R1B:  c |= RESP_R1B;  break;
	case MMC_RSP_R2:   c |= RESP_R2;   break;
	case MMC_RSP_R3:   c |= RESP_R3;   break;
	default:
		return -EINVAL;
	}

	/* No interrupts so this may not be cleared */
	sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);

	sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_CMDRESPEND |
			sd_ctrl_read32(base, CTL_IRQ_MASK));
	sd_ctrl_write32(base, CTL_ARG_REG, cmd->arg);
	sd_ctrl_write16(base, CTL_SD_CMD, c);


	sd_ctrl_write32(base, CTL_IRQ_MASK,
			~(TMIO_STAT_CMDRESPEND | ALL_ERROR) &
			sd_ctrl_read32(base, CTL_IRQ_MASK));

	err = sdhi_boot_wait_resp_end(base);
	if (err)
		return err;

	cmd->resp[0] = sd_ctrl_read32(base, CTL_RESPONSE);

	return 0;
}
Beispiel #6
0
static void
tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
{
	void *base = host->ctl_base;
	struct mmc_data *data = host->data;
	int c = cmd->opcode;

	if(cmd->opcode == MMC_STOP_TRANSMISSION) {
		writew(0x001, host->ctl_base + TMIO_CTRL_STOP_INTERNAL_ACTION_REG);
		return;
	}

	switch(mmc_resp_type(cmd)) {
		case MMC_RSP_NONE: c |= RESP_NONE; break;
		case MMC_RSP_R1:   c |= RESP_R1;   break;
		case MMC_RSP_R1B:  c |= RESP_R1B;  break;
		case MMC_RSP_R2:   c |= RESP_R2;   break;
		case MMC_RSP_R3:   c |= RESP_R3;   break;
		default:
			DBG("Unknown response type %d\n", mmc_resp_type(cmd));
	}

	host->cmd = cmd;

// FIXME - this seems to be ok comented out but the spec say this bit should
//         be set when issuing app commands... the upper MC code doesnt help us
//         here, though.
//	if(cmd->flags & MMC_FLAG_ACMD)
//		c |= APP_CMD;
	if(data) {
		c |= DATA_PRESENT;
		if(data->blocks > 1) {
			writew(0x100, host->ctl_base + TMIO_CTRL_STOP_INTERNAL_ACTION_REG);
			c |= TRANSFER_MULTI;
		}
		if(data->flags & MMC_DATA_READ)
			c |= TRANSFER_READ;
	}

	enable_mmc_irqs(host, TMIO_MASK_CMD);

	/* Fire off the command */
	write_long_reg(cmd->arg, base + TMIO_CTRL_ARG_REG_BASE);
	writew(c, base + TMIO_CTRL_CMD_REG);
}
Beispiel #7
0
/*
 * Handle a command that has been completed
 */
static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
{
	struct mmc_command *cmd = host->cmd;
	struct mmc_data *data = cmd->data;

	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));

	cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
	cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
	cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
	cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));

	if (host->buffer) {
		dma_unmap_single(NULL,
				host->physical_address, host->total_length,
				DMA_TO_DEVICE);
		kfree(host->buffer);
		host->buffer = NULL;
	}

	pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
		 status, at91_mci_read(host, AT91_MCI_SR),
		 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);

	if (status & AT91_MCI_ERRORS) {
		if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
			cmd->error = 0;
		}
		else {
			if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
				if (data) {
					if (status & AT91_MCI_DTOE)
						data->error = -ETIMEDOUT;
					else if (status & AT91_MCI_DCRCE)
						data->error = -EILSEQ;
				}
			} else {
				if (status & AT91_MCI_RTOE)
					cmd->error = -ETIMEDOUT;
				else if (status & AT91_MCI_RCRCE)
					cmd->error = -EILSEQ;
				else
					cmd->error = -EIO;
			}

			pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
				cmd->error, data ? data->error : 0,
				 cmd->opcode, cmd->retries);
		}
	}
	else
		cmd->error = 0;

	at91_mci_process_next(host);
}
Beispiel #8
0
static void rcv_resp(struct ak880xmci_host *host, struct mmc_command *cmd)
{
	cmd->resp[0] = mci_read(host, MMC_RESP1);
	cmd->resp[1] = mci_read(host, MMC_RESP2);
	cmd->resp[2] = mci_read(host, MMC_RESP3);
	cmd->resp[3] = mci_read(host, MMC_RESP4);
	if (mmc_resp_type(cmd) & MMC_RSP_OPCODE) {
		int rsp_opcode = mci_read(host, MMC_CMD_RESP);
		/* dbg("rsp_opcode(%d)", rsp_opcode); */
	}
}
Beispiel #9
0
static void mxs_mmc_ac(struct mxs_mmc_host *host)
{
	struct mxs_ssp *ssp = &host->ssp;
	struct mmc_command *cmd = host->cmd;
	struct dma_async_tx_descriptor *desc;
	u32 ignore_crc, get_resp, long_resp;
	u32 ctrl0, cmd0, cmd1;

	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
			0 : BM_SSP_CTRL0_IGNORE_CRC;
	get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
			BM_SSP_CTRL0_GET_RESP : 0;
	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
			BM_SSP_CTRL0_LONG_RESP : 0;

	ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | get_resp | long_resp;
	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
	cmd1 = cmd->arg;

	if (host->sdio_irq_en) {
		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
	}

	ssp->ssp_pio_words[0] = ctrl0;
	ssp->ssp_pio_words[1] = cmd0;
	ssp->ssp_pio_words[2] = cmd1;
	ssp->dma_dir = DMA_NONE;
	ssp->slave_dirn = DMA_TRANS_NONE;
	desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
	if (!desc)
		goto out;

	dmaengine_submit(desc);
	dma_async_issue_pending(ssp->dmach);
	return;

out:
	dev_warn(mmc_dev(host->mmc),
		 "%s: failed to prep dma\n", __func__);
}
Beispiel #10
0
static void mxs_mmc_request_done(struct mxs_mmc_host *host)
{
	struct mmc_command *cmd = host->cmd;
	struct mmc_data *data = host->data;
	struct mmc_request *mrq = host->mrq;
	struct mxs_ssp *ssp = &host->ssp;

	if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) {
		if (mmc_resp_type(cmd) & MMC_RSP_136) {
			cmd->resp[3] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
			cmd->resp[2] = readl(ssp->base + HW_SSP_SDRESP1(ssp));
			cmd->resp[1] = readl(ssp->base + HW_SSP_SDRESP2(ssp));
			cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP3(ssp));
		} else {
			cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
		}
	}

	if (data) {
		dma_unmap_sg(mmc_dev(host->mmc), data->sg,
			     data->sg_len, ssp->dma_dir);
		/*
		 * If there was an error on any block, we mark all
		 * data blocks as being in error.
		 */
		if (!data->error)
			data->bytes_xfered = data->blocks * data->blksz;
		else
			data->bytes_xfered = 0;

		host->data = NULL;
		if (mrq->stop) {
			mxs_mmc_start_cmd(host, mrq->stop);
			return;
		}
	}

	host->mrq = NULL;
	mmc_request_done(host->mmc, mrq);
}
Beispiel #11
0
/*
 * This function sets up the SDHC registers in order to issue a command.
 *
 * @param priv  Pointer to MMC/SD priv structure
 * @param cmd   Pointer to MMC/SD command structure
 * @param cmdat Value to store in the Command and Data Control registers
 */
static void mxcmci_start_cmd(struct mxcmci_priv *priv, struct mmc_command *cmd,
			     unsigned int cmdat)
{
	unsigned long flags;
	int timeout;
	int ret;

	WARN_ON(priv->cmd != NULL);
	priv->cmd = cmd;

	switch (RSP_TYPE(mmc_resp_type(cmd))) {
	case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6 */
		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1;
		break;
	case RSP_TYPE(MMC_RSP_R3):
		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
		break;
	case RSP_TYPE(MMC_RSP_R2):
		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2;
		break;
	default:
		/* No Response required */
		break;
	}

	if (cmd->opcode == MMC_GO_IDLE_STATE)
		cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */

	if (priv->host->ios.bus_width == MMC_BUS_WIDTH_4)
		cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;

	local_irq_save(flags);
	mxcmci_start_clock(priv);

	__raw_writel(cmd->opcode, priv->base + MMC_CMD);
	__raw_writel(cmd->arg, priv->base + MMC_ARG);

	__raw_writel(cmdat, priv->base + MMC_CMD_DAT_CONT);
	local_irq_restore(flags);

	timeout = wait_for_completion_timeout(&priv->comp_cmd_done,
					      msecs_to_jiffies(1000));
	if (timeout == 0) {
		dev_err(priv->host->parent, "wait cmd_done timeout\n");
		cmd->error = -ETIMEDOUT;
	}

	ret = mxcmci_cmd_done(priv, 0);
	if (ret)
		return;
}
Beispiel #12
0
static void usdhi6_resp_read(struct usdhi6_host *host)
{
	struct mmc_command *cmd = host->mrq->cmd;
	u32 *rsp = cmd->resp, tmp = 0;
	int i;

/*
 * RSP10	39-8
 * RSP32	71-40
 * RSP54	103-72
 * RSP76	127-104
 * R2-type response:
 * resp[0]	= r[127..96]
 * resp[1]	= r[95..64]
 * resp[2]	= r[63..32]
 * resp[3]	= r[31..0]
 * Other responses:
 * resp[0]	= r[39..8]
 */

	if (mmc_resp_type(cmd) == MMC_RSP_NONE)
		return;

	if (!(host->irq_status & USDHI6_SD_INFO1_RSP_END)) {
		dev_err(mmc_dev(host->mmc),
			"CMD%d: response expected but is missing!\n", cmd->opcode);
		return;
	}

	if (mmc_resp_type(cmd) & MMC_RSP_136)
		for (i = 0; i < 4; i++) {
			if (i)
				rsp[3 - i] = tmp >> 24;
			tmp = usdhi6_read(host, USDHI6_SD_RSP10 + i * 8);
			rsp[3 - i] |= tmp << 8;
		}
	else if (cmd->opcode == MMC_READ_MULTIPLE_BLOCK ||
Beispiel #13
0
static struct cvm_mmc_cr_mods cvm_mmc_get_cr_mods(struct mmc_command *cmd)
{
	struct cvm_mmc_cr_type *cr;
	u8 hardware_ctype, hardware_rtype;
	u8 desired_ctype = 0, desired_rtype = 0;
	struct cvm_mmc_cr_mods r;

	cr = cvm_mmc_cr_types + (cmd->opcode & 0x3f);
	hardware_ctype = cr->ctype;
	hardware_rtype = cr->rtype;
	if (cmd->opcode == MMC_GEN_CMD)
		hardware_ctype = (cmd->arg & 1) ? 1 : 2;

	switch (mmc_cmd_type(cmd)) {
	case MMC_CMD_ADTC:
		desired_ctype = (cmd->data->flags & MMC_DATA_WRITE) ? 2 : 1;
		break;
	case MMC_CMD_AC:
	case MMC_CMD_BC:
	case MMC_CMD_BCR:
		desired_ctype = 0;
		break;
	}

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		desired_rtype = 0;
		break;
	case MMC_RSP_R1:/* MMC_RSP_R5, MMC_RSP_R6, MMC_RSP_R7 */
	case MMC_RSP_R1B:
		desired_rtype = 1;
		break;
	case MMC_RSP_R2:
		desired_rtype = 2;
		break;
	case MMC_RSP_R3: /* MMC_RSP_R4 */
		desired_rtype = 3;
		break;
	}
	r.ctype_xor = desired_ctype ^ hardware_ctype;
	r.rtype_xor = desired_rtype ^ hardware_rtype;
	return r;
}
Beispiel #14
0
/*
 * Handle a command that has been completed
 */
static void at91_mci_completed_command(struct at91mci_host *host)
{
	struct mmc_command *cmd = host->cmd;
	unsigned int status;

	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);

	cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
	cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
	cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
	cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));

	if (host->buffer) {
		dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
		host->buffer = NULL;
	}

	status = at91_mci_read(host, AT91_MCI_SR);

	pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
		 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);

	if (status & AT91_MCI_ERRORS) {
		if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
			cmd->error = 0;
		}
		else {
			if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
				cmd->error = -ETIMEDOUT;
			else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
				cmd->error = -EILSEQ;
			else
				cmd->error = -EIO;

			pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n",
				 cmd->error, cmd->opcode, cmd->retries);
		}
	}
	else
		cmd->error = 0;

	at91_mci_process_next(host);
}
Beispiel #15
0
static int hi_mci_exec_cmd(struct himci_host *host, struct mmc_command *cmd,
		struct mmc_data *data)
{
	union cmd_arg_s  cmd_regs;

	himci_trace(2, "begin");
	himci_assert(host);
	himci_assert(cmd);

	host->cmd = cmd;

	himci_writel(cmd->arg, host->base + MCI_CMDARG);

	cmd_regs.cmd_arg = himci_readl(host->base + MCI_CMD);
	if (data) {
		cmd_regs.bits.data_transfer_expected = 1;
		if (data->flags & (MMC_DATA_WRITE | MMC_DATA_READ))
			cmd_regs.bits.transfer_mode = 0;

		if (data->flags & MMC_DATA_STREAM)
			cmd_regs.bits.transfer_mode = 1;

		if (data->flags & MMC_DATA_WRITE)
			cmd_regs.bits.read_write = 1;
		else if (data->flags & MMC_DATA_READ)
			cmd_regs.bits.read_write = 0;
	} else {
		cmd_regs.bits.data_transfer_expected = 0;
		cmd_regs.bits.transfer_mode = 0;
		cmd_regs.bits.read_write = 0;
	}

	if (cmd == host->mrq->stop) {
		cmd_regs.bits.stop_abort_cmd = 1;
		cmd_regs.bits.wait_prvdata_complete = 0;
	} else {
		cmd_regs.bits.stop_abort_cmd = 0;
		cmd_regs.bits.wait_prvdata_complete = 1;
	}

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		cmd_regs.bits.response_expect = 0;
		cmd_regs.bits.response_length = 0;
		cmd_regs.bits.check_response_crc = 0;
		break;
	case MMC_RSP_R1:
	case MMC_RSP_R1B:
		cmd_regs.bits.response_expect = 1;
		cmd_regs.bits.response_length = 0;
		cmd_regs.bits.check_response_crc = 1;
		break;
	case MMC_RSP_R2:
		cmd_regs.bits.response_expect = 1;
		cmd_regs.bits.response_length = 1;
		cmd_regs.bits.check_response_crc = 1;
		break;
	case MMC_RSP_R3:
		cmd_regs.bits.response_expect = 1;
		cmd_regs.bits.response_length = 0;
		cmd_regs.bits.check_response_crc = 0;
		break;
	default:
		himci_error("hi_mci: unhandled response type %02x\n",
				mmc_resp_type(cmd));
		return -EINVAL;
	}

	himci_trace(3, "send cmd of card is cmd->opcode = %d ", cmd->opcode);
	if (cmd->opcode == MMC_GO_IDLE_STATE)
		cmd_regs.bits.send_initialization = 1;
	else
		cmd_regs.bits.send_initialization = 0;

	cmd_regs.bits.card_number = 0;
	cmd_regs.bits.cmd_index = cmd->opcode;
	cmd_regs.bits.send_auto_stop = 0;
	cmd_regs.bits.start_cmd = 1;
	cmd_regs.bits.update_clk_reg_only = 0;
	himci_writel(cmd_regs.cmd_arg, host->base + MCI_CMD);

	if (hi_mci_wait_cmd(host) != 0) {
		himci_trace(3, "send card cmd is failed!");
		return -EINVAL;
	}
	return 0;
}
Beispiel #16
0
static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
		struct mmc_command *cmd)
{
	struct rtsx_pcr *pcr = host->pcr;
	u8 cmd_idx = (u8)cmd->opcode;
	u32 arg = cmd->arg;
	int err = 0;
	int timeout = 100;
	int i;
	u8 *ptr;
	int stat_idx = 0;
	u8 rsp_type;
	int rsp_len = 5;
	bool clock_toggled = false;

	dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
			__func__, cmd_idx, arg);

	/* Response type:
	 * R0
	 * R1, R5, R6, R7
	 * R1b
	 * R2
	 * R3, R4
	 */
	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		rsp_type = SD_RSP_TYPE_R0;
		rsp_len = 0;
		break;
	case MMC_RSP_R1:
		rsp_type = SD_RSP_TYPE_R1;
		break;
	case MMC_RSP_R1 & ~MMC_RSP_CRC:
		rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7;
		break;
	case MMC_RSP_R1B:
		rsp_type = SD_RSP_TYPE_R1b;
		break;
	case MMC_RSP_R2:
		rsp_type = SD_RSP_TYPE_R2;
		rsp_len = 16;
		break;
	case MMC_RSP_R3:
		rsp_type = SD_RSP_TYPE_R3;
		break;
	default:
		dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n");
		err = -EINVAL;
		goto out;
	}

	if (rsp_type == SD_RSP_TYPE_R1b)
		timeout = 3000;

	if (cmd->opcode == SD_SWITCH_VOLTAGE) {
		err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
				0xFF, SD_CLK_TOGGLE_EN);
		if (err < 0)
			goto out;

		clock_toggled = true;
	}

	rtsx_pci_init_cmd(pcr);

	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24));
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16));
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8));
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg);

	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
			0x01, PINGPONG_BUFFER);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER,
			0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
		     SD_TRANSFER_END | SD_STAT_IDLE,
		     SD_TRANSFER_END | SD_STAT_IDLE);

	if (rsp_type == SD_RSP_TYPE_R2) {
		/* Read data from ping-pong buffer */
		for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++)
			rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
		stat_idx = 16;
	} else if (rsp_type != SD_RSP_TYPE_R0) {
		/* Read data from SD_CMDx registers */
		for (i = SD_CMD0; i <= SD_CMD4; i++)
			rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
		stat_idx = 5;
	}

	rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0);

	err = rtsx_pci_send_cmd(pcr, timeout);
	if (err < 0) {
		sd_print_debug_regs(host);
		sd_clear_error(host);
		dev_dbg(sdmmc_dev(host),
			"rtsx_pci_send_cmd error (err = %d)\n", err);
		goto out;
	}

	if (rsp_type == SD_RSP_TYPE_R0) {
		err = 0;
		goto out;
	}

	/* Eliminate returned value of CHECK_REG_CMD */
	ptr = rtsx_pci_get_cmd_data(pcr) + 1;

	/* Check (Start,Transmission) bit of Response */
	if ((ptr[0] & 0xC0) != 0) {
		err = -EILSEQ;
		dev_dbg(sdmmc_dev(host), "Invalid response bit\n");
		goto out;
	}

	/* Check CRC7 */
	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
		if (ptr[stat_idx] & SD_CRC7_ERR) {
			err = -EILSEQ;
			dev_dbg(sdmmc_dev(host), "CRC7 error\n");
			goto out;
		}
	}

	if (rsp_type == SD_RSP_TYPE_R2) {
		/*
		 * The controller offloads the last byte {CRC-7, end bit 1'b1}
		 * of response type R2. Assign dummy CRC, 0, and end bit to the
		 * byte(ptr[16], goes into the LSB of resp[3] later).
		 */
		ptr[16] = 1;

		for (i = 0; i < 4; i++) {
			cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4);
			dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n",
					i, cmd->resp[i]);
		}
	} else {
		cmd->resp[0] = get_unaligned_be32(ptr + 1);
		dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n",
				cmd->resp[0]);
	}

out:
	cmd->error = err;

	if (err && clock_toggled)
		rtsx_pci_write_register(pcr, SD_BUS_STAT,
				SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
}
Beispiel #17
0
static void
mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
{
	u32 cmdreg;
	u32 resptype;
	u32 cmdtype;

	host->cmd = cmd;

	resptype = 0;
	cmdtype = 0;

	/* Our hardware needs to know exact type */
	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		break;
	case MMC_RSP_R1:
	case MMC_RSP_R1B:
		/* resp 1, 1b, 6, 7 */
		resptype = 1;
		break;
	case MMC_RSP_R2:
		resptype = 2;
		break;
	case MMC_RSP_R3:
		resptype = 3;
		break;
	default:
		dev_err(mmc_dev(host->mmc), "Invalid response type: %04x\n", mmc_resp_type(cmd));
		break;
	}

	if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) {
		cmdtype = OMAP_MMC_CMDTYPE_ADTC;
	} else if (mmc_cmd_type(cmd) == MMC_CMD_BC) {
		cmdtype = OMAP_MMC_CMDTYPE_BC;
	} else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) {
		cmdtype = OMAP_MMC_CMDTYPE_BCR;
	} else {
		cmdtype = OMAP_MMC_CMDTYPE_AC;
	}

	cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);

	if (host->current_slot->bus_mode == MMC_BUSMODE_OPENDRAIN)
		cmdreg |= 1 << 6;

	if (cmd->flags & MMC_RSP_BUSY)
		cmdreg |= 1 << 11;

	if (host->data && !(host->data->flags & MMC_DATA_WRITE))
		cmdreg |= 1 << 15;

	mod_timer(&host->cmd_abort_timer, jiffies + HZ/2);

	OMAP_MMC_WRITE(host, CTO, 200);
	OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
	OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
	OMAP_MMC_WRITE(host, IE,
		       OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
		       OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
		       OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
		       OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
		       OMAP_MMC_STAT_END_OF_DATA);
	OMAP_MMC_WRITE(host, CMD, cmdreg);
}
Beispiel #18
0
static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
				struct mmc_command *cmd, struct mmc_data *data)
{
	u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		break;
	case MMC_RSP_R1:
		mmccmd |= SD_CMD_RT_1;
		break;
	case MMC_RSP_R1B:
		mmccmd |= SD_CMD_RT_1B;
		break;
	case MMC_RSP_R2:
		mmccmd |= SD_CMD_RT_2;
		break;
	case MMC_RSP_R3:
		mmccmd |= SD_CMD_RT_3;
		break;
	default:
		printk(KERN_INFO "au1xmmc: unhandled response type %02x\n",
			mmc_resp_type(cmd));
		return -EINVAL;
	}

	if (data) {
		if (data->flags & MMC_DATA_READ) {
			if (data->blocks > 1)
				mmccmd |= SD_CMD_CT_4;
			else
				mmccmd |= SD_CMD_CT_2;
		} else if (data->flags & MMC_DATA_WRITE) {
			if (data->blocks > 1)
				mmccmd |= SD_CMD_CT_3;
			else
				mmccmd |= SD_CMD_CT_1;
		}
	}

	au_writel(cmd->arg, HOST_CMDARG(host));
	au_sync();

	if (wait)
		IRQ_OFF(host, SD_CONFIG_CR);

	au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
	au_sync();

	/* Wait for the command to go on the line */
	while (au_readl(HOST_CMD(host)) & SD_CMD_GO)
		/* nop */;

	/* Wait for the command to come back */
	if (wait) {
		u32 status = au_readl(HOST_STATUS(host));

		while (!(status & SD_STATUS_CR))
			status = au_readl(HOST_STATUS(host));

		/* Clear the CR status */
		au_writel(SD_STATUS_CR, HOST_STATUS(host));

		IRQ_ON(host, SD_CONFIG_CR);
	}

	return 0;
}
Beispiel #19
0
/* Send the ac command to the device */
static void stmp3xxx_mmc_ac(struct stmp3xxx_mmc_host *host)
{
	struct mmc_command *cmd = host->cmd;
	struct stmp3xxx_dma_descriptor *dma_desc = &host->dma_desc;
	u32 ignore_crc, resp, long_resp;
	u32 ssp_ctrl0;
	u32 ssp_cmd0;
	u32 ssp_cmd1;

	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
	    0 : BM_SSP_CTRL0_IGNORE_CRC;
	resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
	    BM_SSP_CTRL0_GET_RESP : 0;
	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
	    BM_SSP_CTRL0_LONG_RESP : 0;

	dma_desc->command->cmd =
	    BM_APBH_CHn_CMD_WAIT4ENDCMD |
	    BM_APBH_CHn_CMD_SEMAPHORE |
	    BM_APBH_CHn_CMD_IRQONCMPLT |
	    BF(0, APBH_CHn_CMD_XFER_COUNT) |
	    BF(3, APBH_CHn_CMD_CMDWORDS) | BF(0, APBH_CHn_CMD_COMMAND);

	ssp_ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | long_resp | resp;
	ssp_cmd0 = BF(cmd->opcode, SSP_CMD0_CMD);
	ssp_cmd1 = BF(cmd->arg, SSP_CMD1_CMD_ARG);

	dma_desc->command->pio_words[0] = ssp_ctrl0;
	dma_desc->command->pio_words[1] = ssp_cmd0;
	dma_desc->command->pio_words[2] = ssp_cmd1;

	stmp3xxx_dma_reset_channel(host->dmach);
	init_completion(&host->dma_done);
	stmp3xxx_dma_go(host->dmach, dma_desc, 1);
	wait_for_completion(&host->dma_done);

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		while (__raw_readl(host->ssp_base + HW_SSP_CTRL0)
		       & BM_SSP_CTRL0_RUN)
			continue;
		break;
	case MMC_RSP_R1:
	case MMC_RSP_R1B:
	case MMC_RSP_R3:
		cmd->resp[0] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP0);
		break;
	case MMC_RSP_R2:
		cmd->resp[3] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP0);
		cmd->resp[2] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP1);
		cmd->resp[1] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP2);
		cmd->resp[0] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP3);
		break;
	default:
		dev_warn(host->dev, "Unsupported response type 0x%x\n",
			 mmc_resp_type(cmd));
		BUG();
		break;
	}

	cmd->error = stmp3xxx_mmc_cmd_error(host->status);

	if (stmp3xxx_dma_running(host->dmach))
		dev_dbg(host->dev, "DMA command not finished\n");

	if (cmd->error) {
		dev_dbg(host->dev, "Command error 0x%x\n", cmd->error);
		stmp3xxx_dma_reset_channel(host->dmach);
	}
}
Beispiel #20
0
/*
 * Send a command
 */
static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
{
	unsigned int cmdr, mr;
	unsigned int block_length;
	struct mmc_data *data = cmd->data;

	unsigned int blocks;
	unsigned int ier = 0;

	host->cmd = cmd;

	/* Needed for leaving busy state before CMD1 */
	if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
		pr_debug("Clearing timeout\n");
		at91_mci_write(host, AT91_MCI_ARGR, 0);
		at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
		while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
			/* spin */
			pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
		}
	}

	cmdr = cmd->opcode;

	if (mmc_resp_type(cmd) == MMC_RSP_NONE)
		cmdr |= AT91_MCI_RSPTYP_NONE;
	else {
		/* if a response is expected then allow maximum response latancy */
		cmdr |= AT91_MCI_MAXLAT;
		/* set 136 bit response for R2, 48 bit response otherwise */
		if (mmc_resp_type(cmd) == MMC_RSP_R2)
			cmdr |= AT91_MCI_RSPTYP_136;
		else
			cmdr |= AT91_MCI_RSPTYP_48;
	}

	if (data) {

		if ( data->blksz & 0x3 ) {
			pr_debug("Unsupported block size\n");
			cmd->error = -EINVAL;
			mmc_request_done(host->mmc, host->request);
			return;
		}

		block_length = data->blksz;
		blocks = data->blocks;

		/* always set data start - also set direction flag for read */
		if (data->flags & MMC_DATA_READ)
			cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
		else if (data->flags & MMC_DATA_WRITE)
			cmdr |= AT91_MCI_TRCMD_START;

		if (data->flags & MMC_DATA_STREAM)
			cmdr |= AT91_MCI_TRTYP_STREAM;
		if (data->blocks > 1)
			cmdr |= AT91_MCI_TRTYP_MULTIPLE;
	}
	else {
		block_length = 0;
		blocks = 0;
	}

	if (host->flags & FL_SENT_STOP)
		cmdr |= AT91_MCI_TRCMD_STOP;

	if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
		cmdr |= AT91_MCI_OPDCMD;

	/*
	 * Set the arguments and send the command
	 */
	pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));

	if (!data) {
		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
		at91_mci_write(host, ATMEL_PDC_RPR, 0);
		at91_mci_write(host, ATMEL_PDC_RCR, 0);
		at91_mci_write(host, ATMEL_PDC_RNPR, 0);
		at91_mci_write(host, ATMEL_PDC_RNCR, 0);
		at91_mci_write(host, ATMEL_PDC_TPR, 0);
		at91_mci_write(host, ATMEL_PDC_TCR, 0);
		at91_mci_write(host, ATMEL_PDC_TNPR, 0);
		at91_mci_write(host, ATMEL_PDC_TNCR, 0);
		ier = AT91_MCI_CMDRDY;
	} else {
		/* zero block length and PDC mode */
		mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
		at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);

		/*
		 * Disable the PDC controller
		 */
		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);

		if (cmdr & AT91_MCI_TRCMD_START) {
			data->bytes_xfered = 0;
			host->transfer_index = 0;
			host->in_use_index = 0;
			if (cmdr & AT91_MCI_TRDIR) {
				/*
				 * Handle a read
				 */
				host->buffer = NULL;
				host->total_length = 0;

				at91_mci_pre_dma_read(host);
				ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
			}
			else {
				/*
				 * Handle a write
				 */
				host->total_length = block_length * blocks;
				host->buffer = dma_alloc_coherent(NULL,
						host->total_length,
						&host->physical_address, GFP_KERNEL);

				at91_mci_sg_to_dma(host, data);

				pr_debug("Transmitting %d bytes\n", host->total_length);

				at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
				at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
				ier = AT91_MCI_CMDRDY;
			}
		}
	}

	/*
	 * Send the command and then enable the PDC - not the other way round as
	 * the data sheet says
	 */

	at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
	at91_mci_write(host, AT91_MCI_CMDR, cmdr);

	if (cmdr & AT91_MCI_TRCMD_START) {
		if (cmdr & AT91_MCI_TRDIR)
			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
	}

	/* Enable selected interrupts */
	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
}
static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
{
	unsigned int cmdr, mr;
	unsigned int block_length;
	struct mmc_data *data = cmd->data;

	unsigned int blocks;
	unsigned int ier = 0;

	host->cmd = cmd;

	
	if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
		pr_debug("Clearing timeout\n");
		at91_mci_write(host, AT91_MCI_ARGR, 0);
		at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
		while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
			
			pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
		}
	}

	cmdr = cmd->opcode;

	if (mmc_resp_type(cmd) == MMC_RSP_NONE)
		cmdr |= AT91_MCI_RSPTYP_NONE;
	else {
		
		cmdr |= AT91_MCI_MAXLAT;
		
		if (mmc_resp_type(cmd) == MMC_RSP_R2)
			cmdr |= AT91_MCI_RSPTYP_136;
		else
			cmdr |= AT91_MCI_RSPTYP_48;
	}

	if (data) {

		if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
			if (data->blksz & 0x3) {
				pr_debug("Unsupported block size\n");
				cmd->error = -EINVAL;
				mmc_request_done(host->mmc, host->request);
				return;
			}
			if (data->flags & MMC_DATA_STREAM) {
				pr_debug("Stream commands not supported\n");
				cmd->error = -EINVAL;
				mmc_request_done(host->mmc, host->request);
				return;
			}
		}

		block_length = data->blksz;
		blocks = data->blocks;

		
		if (data->flags & MMC_DATA_READ)
			cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
		else if (data->flags & MMC_DATA_WRITE)
			cmdr |= AT91_MCI_TRCMD_START;

		if (cmd->opcode == SD_IO_RW_EXTENDED) {
			cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK;
		} else {
			if (data->flags & MMC_DATA_STREAM)
				cmdr |= AT91_MCI_TRTYP_STREAM;
			if (data->blocks > 1)
				cmdr |= AT91_MCI_TRTYP_MULTIPLE;
		}
	}
	else {
		block_length = 0;
		blocks = 0;
	}

	if (host->flags & FL_SENT_STOP)
		cmdr |= AT91_MCI_TRCMD_STOP;

	if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
		cmdr |= AT91_MCI_OPDCMD;

	pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));

	if (!data) {
		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
		at91_mci_write(host, ATMEL_PDC_RPR, 0);
		at91_mci_write(host, ATMEL_PDC_RCR, 0);
		at91_mci_write(host, ATMEL_PDC_RNPR, 0);
		at91_mci_write(host, ATMEL_PDC_RNCR, 0);
		at91_mci_write(host, ATMEL_PDC_TPR, 0);
		at91_mci_write(host, ATMEL_PDC_TCR, 0);
		at91_mci_write(host, ATMEL_PDC_TNPR, 0);
		at91_mci_write(host, ATMEL_PDC_TNCR, 0);
		ier = AT91_MCI_CMDRDY;
	} else {
		
		mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
		mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
		mr |= (block_length << 16);
		mr |= AT91_MCI_PDCMODE;
		at91_mci_write(host, AT91_MCI_MR, mr);

		if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
			at91_mci_write(host, AT91_MCI_BLKR,
				AT91_MCI_BLKR_BCNT(blocks) |
				AT91_MCI_BLKR_BLKLEN(block_length));

		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);

		if (cmdr & AT91_MCI_TRCMD_START) {
			data->bytes_xfered = 0;
			host->transfer_index = 0;
			host->in_use_index = 0;
			if (cmdr & AT91_MCI_TRDIR) {
				host->total_length = 0;

				at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
				at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
					(blocks * block_length) : (blocks * block_length) / 4);
				at91_mci_write(host, ATMEL_PDC_RNPR, 0);
				at91_mci_write(host, ATMEL_PDC_RNCR, 0);

				ier = AT91_MCI_ENDRX ;
			}
			else {
				host->total_length = block_length * blocks;
				if (at91mci_is_mci1rev2xx())
					if (host->total_length < 12)
						host->total_length = 12;

				at91_mci_sg_to_dma(host, data);

				pr_debug("Transmitting %d bytes\n", host->total_length);

				at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
				at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
						host->total_length : host->total_length / 4);

				ier = AT91_MCI_CMDRDY;
			}
		}
	}


	at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
	at91_mci_write(host, AT91_MCI_CMDR, cmdr);

	if (cmdr & AT91_MCI_TRCMD_START) {
		if (cmdr & AT91_MCI_TRDIR)
			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
	}

	
	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
}
Beispiel #22
0
static void jz_mmc_start_cmd(struct jz_mmc_host *host,
			     struct mmc_command *cmd, unsigned int cmdat)
{
	u32 timeout = 0x3fffff;
	unsigned int stat;
	struct jz_mmc_host *hst = host;
	WARN_ON(host->cmd != NULL);
	host->cmd = cmd;

	/* stop MMC clock */
	jz_mmc_stop_clock();

	/* mask interrupts */
	REG_MSC_IMASK = 0xff;

	/* clear status */
	REG_MSC_IREG = 0xff;

	if (cmd->flags & MMC_RSP_BUSY)
		cmdat |= MSC_CMDAT_BUSY;

#define RSP_TYPE(x)	((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
	switch (RSP_TYPE(mmc_resp_type(cmd))) {
	case RSP_TYPE(MMC_RSP_R1):	/* r1,r1b, r6, r7 */
		cmdat |= MSC_CMDAT_RESPONSE_R1;
		r_type = 1;
		break;
	case RSP_TYPE(MMC_RSP_R3):
		cmdat |= MSC_CMDAT_RESPONSE_R3;
		r_type = 1;
		break;
	case RSP_TYPE(MMC_RSP_R2):
		cmdat |= MSC_CMDAT_RESPONSE_R2;
		r_type = 2;
		break;
	default:
		break;
	}
	REG_MSC_CMD = cmd->opcode;

	/* Set argument */
#ifdef CONFIG_JZ_MMC_BUS_1
	if (cmd->opcode == 6) {
		/* set  1 bit sd card bus*/
		if (cmd->arg ==2)  
			REG_MSC_ARG = 0;

		/* set  1 bit mmc card bus*/
		if (cmd->arg == 0x3b70101)
			REG_MSC_ARG = 0x3b70001;
	} else
		REG_MSC_ARG = cmd->arg;
#else
	REG_MSC_ARG = cmd->arg;
#endif

	/* Set command */
	REG_MSC_CMDAT = cmdat;

	/* Send command */
	jz_mmc_start_clock();

	while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES))
		;

	REG_MSC_IREG = MSC_IREG_END_CMD_RES;	/* clear irq flag */
	if (cmd->opcode == 12) {
		while (timeout-- && !(REG_MSC_IREG & MSC_IREG_PRG_DONE))
			;
		REG_MSC_IREG = MSC_IREG_PRG_DONE;	/* clear status */
	}
	if (!mmc_slot_enable) {
		/* It seems that MSC can't report the MSC_STAT_TIME_OUT_RES when
		 * card was removed. We force to return here.
		 */
		cmd->error = -ETIMEDOUT;
		jz_mmc_finish_request(hst, hst->mrq);
		return;
	}

	if (SD_IO_SEND_OP_COND == cmd->opcode) {
		/* 
		 * Don't support SDIO card currently.
		 */
		cmd->error = -ETIMEDOUT;
		jz_mmc_finish_request(hst, hst->mrq);
		return;
	}

	/* Check for status */
	stat = REG_MSC_STAT;
	jz_mmc_cmd_done(hst, stat);
	if (host->data) {
		if (cmd->opcode == MMC_WRITE_BLOCK || cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK)
#ifdef USE_DMA
			jz_mmc_tx_setup_data(host, host->data);
#else
			jz_mmc_send_pio(host);
		else 
			jz_mmc_receive_pio(host);
#endif
	}
Beispiel #23
0
static void mmc_davinci_start_command(struct mmc_davinci_host *host,
				      struct mmc_command *cmd)
{
	u32 cmdreg = 0;
	u32 resptype = 0;
	u32 cmdtype = 0;
	unsigned long flags;

	host->cmd = cmd;

	resptype = 0;
	cmdtype = 0;

	switch (RSP_TYPE(mmc_resp_type(cmd))) {
	case RSP_TYPE(MMC_RSP_R1):
		/* resp 1, resp 1b */
		resptype = 1;
		break;
	case RSP_TYPE(MMC_RSP_R2):
		resptype = 2;
		break;
	case RSP_TYPE(MMC_RSP_R3):
		resptype = 3;
		break;
	default:
		break;
	}

	/* Protocol layer does not provide command type, but our hardware
	 * needs it!
	 * any data transfer means adtc type (but that information is not
	 * in command structure, so we flagged it into host struct.)
	 * However, telling bc, bcr and ac apart based on response is
	 * not foolproof:
	 * CMD0  = bc  = resp0  CMD15 = ac  = resp0
	 * CMD2  = bcr = resp2  CMD10 = ac  = resp2
	 *
	 * Resolve to best guess with some exception testing:
	 * resp0 -> bc, except CMD15 = ac
	 * rest are ac, except if opendrain
	 */

	if (host->data_dir)
		cmdtype = DAVINCI_MMC_CMDTYPE_ADTC;
	else if (resptype == 0 && cmd->opcode != 15)
		cmdtype = DAVINCI_MMC_CMDTYPE_BC;
	else if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
		cmdtype = DAVINCI_MMC_CMDTYPE_BCR;
	else
		cmdtype = DAVINCI_MMC_CMDTYPE_AC;

	/*
	 * Set command Busy or not
	 * Linux core sending BUSY which is not defined for cmd 24
	 * as per mmc standard
	 */
	if (cmd->flags & MMC_RSP_BUSY)
		if (cmd->opcode != 24)
			cmdreg = cmdreg | (1 << 8);

	/* Set command index */
	cmdreg |= cmd->opcode;

	/* Setting initialize clock */
	if (cmd->opcode == 0)
		cmdreg = cmdreg | (1 << 14);

	/* Set for generating DMA Xfer event */
	if ((host->do_dma == 1) && (host->data != NULL)
	    && ((cmd->opcode == 18) || (cmd->opcode == 25)
		|| (cmd->opcode == 24) || (cmd->opcode == 17)))
		cmdreg = cmdreg | (1 << 16);

	/* Setting whether command involves data transfer or not */
	if (cmdtype == DAVINCI_MMC_CMDTYPE_ADTC)
		cmdreg = cmdreg | (1 << 13);

	/* Setting whether stream or block transfer */
	if (cmd->flags & MMC_DATA_STREAM)
		cmdreg = cmdreg | (1 << 12);

	/* Setting whether data read or write */
	if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
		cmdreg = cmdreg | (1 << 11);

	/* Setting response type */
	cmdreg = cmdreg | (resptype << 9);

	if (host->bus_mode == MMC_BUSMODE_PUSHPULL)
		cmdreg = cmdreg | (1 << 7);

	/* set Command timeout */
	DAVINCI_MMC_WRITEW(host, TOR, 0xFFFF);

	/* Enable interrupt */
	if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
		if (host->do_dma != 1)
			DAVINCI_MMC_WRITEW(host, IM, (DAVINCI_MMC_EVENT_EOFCMD |
				      DAVINCI_MMC_EVENT_WRITE |
				      DAVINCI_MMC_EVENT_ERROR_CMDCRC |
				      DAVINCI_MMC_EVENT_ERROR_DATACRC |
				      DAVINCI_MMC_EVENT_ERROR_CMDTIMEOUT |
				      DAVINCI_MMC_EVENT_ERROR_DATATIMEOUT |
				      DAVINCI_MMC_EVENT_BLOCK_XFERRED));
		else
			DAVINCI_MMC_WRITEW(host, IM, (DAVINCI_MMC_EVENT_EOFCMD |
				      DAVINCI_MMC_EVENT_ERROR_CMDCRC |
				      DAVINCI_MMC_EVENT_ERROR_DATACRC |
				      DAVINCI_MMC_EVENT_ERROR_CMDTIMEOUT |
				      DAVINCI_MMC_EVENT_ERROR_DATATIMEOUT |
				      DAVINCI_MMC_EVENT_BLOCK_XFERRED));
	} else if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
		if (host->do_dma != 1)
			DAVINCI_MMC_WRITEW(host, IM, (DAVINCI_MMC_EVENT_EOFCMD |
				      DAVINCI_MMC_EVENT_READ |
				      DAVINCI_MMC_EVENT_ERROR_CMDCRC |
				      DAVINCI_MMC_EVENT_ERROR_DATACRC |
				      DAVINCI_MMC_EVENT_ERROR_CMDTIMEOUT |
				      DAVINCI_MMC_EVENT_ERROR_DATATIMEOUT |
				      DAVINCI_MMC_EVENT_BLOCK_XFERRED));
		else
			DAVINCI_MMC_WRITEW(host, IM, (DAVINCI_MMC_EVENT_EOFCMD |
				      DAVINCI_MMC_EVENT_ERROR_CMDCRC |
				      DAVINCI_MMC_EVENT_ERROR_DATACRC |
				      DAVINCI_MMC_EVENT_ERROR_CMDTIMEOUT |
				      DAVINCI_MMC_EVENT_ERROR_DATATIMEOUT |
				      DAVINCI_MMC_EVENT_BLOCK_XFERRED));
	} else
		DAVINCI_MMC_WRITEW(host, IM, (DAVINCI_MMC_EVENT_EOFCMD |
				      DAVINCI_MMC_EVENT_ERROR_CMDCRC |
				      DAVINCI_MMC_EVENT_ERROR_DATACRC |
				      DAVINCI_MMC_EVENT_ERROR_CMDTIMEOUT |
				      DAVINCI_MMC_EVENT_ERROR_DATATIMEOUT));

	/*
	 * It is required by controoler b4 WRITE command that
	 * FIFO should be populated with 32 bytes
	 */
	if ((host->data_dir == DAVINCI_MMC_DATADIR_WRITE) &&
	    (cmdtype == DAVINCI_MMC_CMDTYPE_ADTC) && (host->do_dma != 1))
		davinci_fifo_data_trans(host);

	if (cmd->opcode == 7) {
		spin_lock_irqsave(&host->mmc_lock, flags);
		host->is_card_removed = 0;
		host->new_card_state = 1;
		host->is_card_initialized = 1;
		host->old_card_state = host->new_card_state;
		host->is_init_progress = 0;
		spin_unlock_irqrestore(&host->mmc_lock, flags);
	}
	if (cmd->opcode == 1 || cmd->opcode == 41) {
		spin_lock_irqsave(&host->mmc_lock, flags);
		host->is_card_initialized = 0;
		host->is_init_progress = 1;
		spin_unlock_irqrestore(&host->mmc_lock, flags);
	}

	host->is_core_command = 1;
	DAVINCI_MMC_WRITEL(host, ARGHL, cmd->arg);
	DAVINCI_MMC_WRITEL(host, CMD, cmdreg);
}
Beispiel #24
0
static void sslsd_cmd_done(sslsd_host *host, sd_cmd_p c)
{
	struct mmc_command	*cmd;

	del_timer(&host->timer);
	cmd = host->pcmd;

//printk("sslsd: cmd_done info - cmd=%d arg=%08X flag=%02X rt=%d\n", 
//c->cmd, c->arg, c->flag, c->rt);

	if (mmc_resp_type(cmd) != MMC_RSP_R2)
	{
		struct mmc_data		*d;

		d = cmd->data;
		cmd->resp[0] = c->rsp;
//printk("sslsd: cmd_done info - resp %08X\n", c->rsp);
		if (d)
		{
			struct scatterlist	*sg;
			sd_dat_p			dat;
			int					len;
			int					card;

			card = sslsd_card_type(host->mmc->card);
			dat = c->dat;
			len = dat->actual;
			if (!len)
			{
				if (!host->retry || (card & SSLSD_CARD_SDIO))
				{
					goto l_done;
				}
				host->retry = 0;
			}

			/* ignore any errors & retry as long as there is progress */
			c->rt = 0;
			sg = host->sg;
			len *= dat->blk;
#if SD_DMA && IO_MAP==3
			/* copy read data from EBM buffer */
			io_rds(ebm_mem + host->sgofs, sg_virt(sg) + host->sgofs, len);
#endif
			d->bytes_xfered += len;

			if (card & SSLSD_CARD_SDIO)
			{
				/* not sure if we can continue transfer from last point */
				goto l_done;
			}

#ifndef NSD_HANDLE_SG_N_ERR
			/* do remainder of scatter page */
			if (dat->actual < dat->count)
			{
				host->sgofs += len;
				goto l_next;
			}

			/* go to next scatter page */
			if (sg < host->sgn)
			{
				sg++;
				host->retry = 1;
				host->sg = sg;
				host->sgofs = 0;

l_next:
				c->arg += (card & SSLSD_CARD_BLKADR) ? dat->actual : len;
				sslsd_map(sg, c, dat, host->sgofs);
				if (sdhc_cmd(&host->hw, c))
				{
					goto l_done;
				}
				return;
			}
#endif

l_done:
#if SD_DMA && IO_MAP==1
			/* data xfer completed for scatter list - unmap it */
			if (c->flag & SDCMD_F_DMA)
			{
				dma_unmap_sg(mmc_dev(host->mmc), host->sg, host->sgc, 
					(c->flag & SDCMD_F_WR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
			}
#endif
		}
	}

	if (c->rt)
	{
printk("sslsd: cmd_done err - cmd=%d arg=%08X fl=%02X rsp=%08X rt=%d\n", 
c->cmd, c->arg, c->flag, c->rsp, c->rt);
if (c->dat) printk("cnt=%d act=%d\n", c->dat->count, c->dat->actual);

		switch (c->rt)
		{
			case SDHC_RET_TOUT:
			case SDHC_RET_CMD_TOUT:
			case SDHC_RET_DAT_TOUT:
				cmd->error = -ETIMEDOUT;
				break;

			case SDHC_RET_DAT_LINE:
			case SDHC_RET_CMD_LINE:
				cmd->error = -EILSEQ;
				break;

			case SDHC_RET_REM:
				cmd->error = -ENOMEDIUM;
				break;

			default:
				cmd->error = -EIO;
				break;
		}
	}

	mmc_request_done(host->mmc, cmd->mrq);
}
Beispiel #25
0
/* Send adtc command to the card */
static void stmp3xxx_mmc_adtc(struct stmp3xxx_mmc_host *host)
{
	struct mmc_command *cmd = host->cmd;
	struct stmp3xxx_dma_descriptor *dma_desc = &host->dma_desc;
	int ignore_crc, resp, long_resp;
	int is_reading = 0;
	unsigned int copy_size;

	u32 ssp_ctrl0;
	u32 ssp_cmd0;
	u32 ssp_cmd1;
	u32 timeout;
	u32 val;

	u32 data_size = cmd->data->blksz * cmd->data->blocks;
	u32 log2_block_size;

	ignore_crc = mmc_resp_type(cmd) & MMC_RSP_CRC ? 0 : 1;
	resp = mmc_resp_type(cmd) & MMC_RSP_PRESENT ? 1 : 0;
	long_resp = mmc_resp_type(cmd) & MMC_RSP_136 ? 1 : 0;

	dev_dbg(host->dev, "ADTC command:\n"
		"response: %d, ignore crc: %d\n"
		"data list: %u, blocksz: %u, blocks: %u, timeout: %uns %uclks, "
		"flags: 0x%x\n", resp, ignore_crc, cmd->data->sg_len,
		cmd->data->blksz, cmd->data->blocks, cmd->data->timeout_ns,
		cmd->data->timeout_clks, cmd->data->flags);

	if (cmd->data->flags & MMC_DATA_WRITE) {
		dev_dbg(host->dev, "Data Write\n");
		copy_size = stmp3xxx_sg_dma_copy(host, data_size, 1);
		BUG_ON(copy_size < data_size);
		is_reading = 0;
		if (!host->regulator)
			__init_reg(host->dev, &host->regulator);
		if (host->regulator)
			regulator_set_current_limit(host->regulator,
						    host->write_uA,
						    host->write_uA);
	} else if (cmd->data->flags & MMC_DATA_READ) {
		dev_dbg(host->dev, "Data Read\n");
		is_reading = 1;
		if (!host->regulator)
			__init_reg(host->dev, &host->regulator);
		if (host->regulator)
			regulator_set_current_limit(host->regulator,
						    host->read_uA,
						    host->read_uA);
	} else {
		dev_warn(host->dev, "Unsuspported data mode, 0x%x\n",
			 cmd->data->flags);
		BUG();
	}

	BUG_ON(cmd->data->flags & MMC_DATA_STREAM);
	BUG_ON((data_size % 8) > 0);

	dma_desc->command->cmd =
	    BM_APBH_CHn_CMD_WAIT4ENDCMD |
	    BM_APBH_CHn_CMD_SEMAPHORE |
	    BM_APBH_CHn_CMD_IRQONCMPLT |
	    BF(data_size, APBH_CHn_CMD_XFER_COUNT) |
	    BF(3, APBH_CHn_CMD_CMDWORDS);

	/* when is_reading is set, DMA controller performs WRITE operation. */
	dma_desc->command->cmd |=
	    BF(is_reading ? BV_APBH_CHn_CMD_COMMAND__DMA_WRITE :
			     BV_APBH_CHn_CMD_COMMAND__DMA_READ,
			     APBH_CHn_CMD_COMMAND);
	ssp_ctrl0 =
	    (ignore_crc ? BM_SSP_CTRL0_IGNORE_CRC : 0) | (resp ?
							  BM_SSP_CTRL0_GET_RESP
							  : 0) | (long_resp ?
								  BM_SSP_CTRL0_LONG_RESP
								  : 0) |
	    (is_reading ? BM_SSP_CTRL0_READ : 0) | BM_SSP_CTRL0_DATA_XFER |
	    BM_SSP_CTRL0_WAIT_FOR_IRQ | BM_SSP_CTRL0_ENABLE | BF(data_size,
								 SSP_CTRL0_XFER_COUNT)
	    | BF(host->bus_width_4 ? BV_SSP_CTRL0_BUS_WIDTH__FOUR_BIT :
				     BV_SSP_CTRL0_BUS_WIDTH__ONE_BIT,
				     SSP_CTRL0_BUS_WIDTH);

	/*
	 * We need to set the hardware register to the logarithm to base 2 of
	 * the block size.
	 */
	log2_block_size = ilog2(cmd->data->blksz);

	ssp_cmd0 =
	    BF(log2_block_size, SSP_CMD0_BLOCK_SIZE) |
	    BF(cmd->opcode, SSP_CMD0_CMD) |
	    BF(cmd->data->blocks - 1, SSP_CMD0_BLOCK_COUNT);

	if (cmd->opcode == 12)
		ssp_cmd0 |= BM_SSP_CMD0_APPEND_8CYC;

	ssp_cmd1 = BF(cmd->arg, SSP_CMD1_CMD_ARG);

	dma_desc->command->pio_words[0] = ssp_ctrl0;
	dma_desc->command->pio_words[1] = ssp_cmd0;
	dma_desc->command->pio_words[2] = ssp_cmd1;

	/* Set the timeout count */
	timeout = stmp3xxx_ns_to_ssp_ticks(host->clkrt, cmd->data->timeout_ns);
	val = __raw_readl(host->ssp_base + HW_SSP_TIMING);
	val &= ~(BM_SSP_TIMING_TIMEOUT);
	val |= BF(timeout, SSP_TIMING_TIMEOUT);
	__raw_writel(val, host->ssp_base + HW_SSP_TIMING);

	init_completion(&host->dma_done);
	stmp3xxx_dma_reset_channel(host->dmach);
	stmp3xxx_dma_go(host->dmach, dma_desc, 1);
	wait_for_completion(&host->dma_done);
	if (host->regulator)
		regulator_set_current_limit(host->regulator, 0, 0);

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		break;
	case MMC_RSP_R1:
	case MMC_RSP_R3:
		cmd->resp[0] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP0);
		break;
	case MMC_RSP_R2:
		cmd->resp[3] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP0);
		cmd->resp[2] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP1);
		cmd->resp[1] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP2);
		cmd->resp[0] =
		    __raw_readl(host->ssp_base + HW_SSP_SDRESP3);
		break;
	default:
		dev_warn(host->dev, "Unsupported response type 0x%x\n",
			 mmc_resp_type(cmd));
		BUG();
		break;
	}

	cmd->error = stmp3xxx_mmc_cmd_error(host->status);

	if (stmp3xxx_dma_running(host->dmach))
		dev_dbg(host->dev, "DMA command not finished\n");

	if (cmd->error) {
		dev_dbg(host->dev, "Command error 0x%x\n", cmd->error);
		stmp3xxx_dma_reset_channel(host->dmach);
	} else {
		if (is_reading)
			cmd->data->bytes_xfered =
			    stmp3xxx_sg_dma_copy(host, data_size, 0);
		else
			cmd->data->bytes_xfered = data_size;

		dev_dbg(host->dev, "Transferred %u bytes\n",
			cmd->data->bytes_xfered);
	}
}
Beispiel #26
0
static void mxs_mmc_adtc(struct mxs_mmc_host *host)
{
	struct mmc_command *cmd = host->cmd;
	struct mmc_data *data = cmd->data;
	struct dma_async_tx_descriptor *desc;
	struct scatterlist *sgl = data->sg, *sg;
	unsigned int sg_len = data->sg_len;
	unsigned int i;

	unsigned short dma_data_dir, timeout;
	enum dma_transfer_direction slave_dirn;
	unsigned int data_size = 0, log2_blksz;
	unsigned int blocks = data->blocks;

	struct mxs_ssp *ssp = &host->ssp;

	u32 ignore_crc, get_resp, long_resp, read;
	u32 ctrl0, cmd0, cmd1, val;

	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
			0 : BM_SSP_CTRL0_IGNORE_CRC;
	get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
			BM_SSP_CTRL0_GET_RESP : 0;
	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
			BM_SSP_CTRL0_LONG_RESP : 0;

	if (data->flags & MMC_DATA_WRITE) {
		dma_data_dir = DMA_TO_DEVICE;
		slave_dirn = DMA_MEM_TO_DEV;
		read = 0;
	} else {
		dma_data_dir = DMA_FROM_DEVICE;
		slave_dirn = DMA_DEV_TO_MEM;
		read = BM_SSP_CTRL0_READ;
	}

	ctrl0 = BF_SSP(host->bus_width, CTRL0_BUS_WIDTH) |
		ignore_crc | get_resp | long_resp |
		BM_SSP_CTRL0_DATA_XFER | read |
		BM_SSP_CTRL0_WAIT_FOR_IRQ |
		BM_SSP_CTRL0_ENABLE;

	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);

	/* get logarithm to base 2 of block size for setting register */
	log2_blksz = ilog2(data->blksz);

	/*
	 * take special care of the case that data size from data->sg
	 * is not equal to blocks x blksz
	 */
	for_each_sg(sgl, sg, sg_len, i)
		data_size += sg->length;

	if (data_size != data->blocks * data->blksz)
		blocks = 1;

	/* xfer count, block size and count need to be set differently */
	if (ssp_is_old(ssp)) {
		ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT);
		cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) |
			BF_SSP(blocks - 1, CMD0_BLOCK_COUNT);
	} else {
		writel(data_size, ssp->base + HW_SSP_XFER_SIZE);
		writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) |
		       BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT),
		       ssp->base + HW_SSP_BLOCK_SIZE);
	}

	if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
	    (cmd->opcode == SD_IO_RW_EXTENDED))
		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;

	cmd1 = cmd->arg;

	if (host->sdio_irq_en) {
		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
	}

	/* set the timeout count */
	timeout = mxs_ns_to_ssp_ticks(ssp->clk_rate, data->timeout_ns);
	val = readl(ssp->base + HW_SSP_TIMING(ssp));
	val &= ~(BM_SSP_TIMING_TIMEOUT);
	val |= BF_SSP(timeout, TIMING_TIMEOUT);
	writel(val, ssp->base + HW_SSP_TIMING(ssp));

	/* pio */
	ssp->ssp_pio_words[0] = ctrl0;
	ssp->ssp_pio_words[1] = cmd0;
	ssp->ssp_pio_words[2] = cmd1;
	ssp->dma_dir = DMA_NONE;
	ssp->slave_dirn = DMA_TRANS_NONE;
	desc = mxs_mmc_prep_dma(host, 0);
	if (!desc)
		goto out;

	/* append data sg */
	WARN_ON(host->data != NULL);
	host->data = data;
	ssp->dma_dir = dma_data_dir;
	ssp->slave_dirn = slave_dirn;
	desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
	if (!desc)
		goto out;

	dmaengine_submit(desc);
	dma_async_issue_pending(ssp->dmach);
	return;
out:
	dev_warn(mmc_dev(host->mmc),
		 "%s: failed to prep dma\n", __func__);
}
static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
		struct mmc_request *mrq, struct mmc_command *cmd, u32 opc)
{
	u32 tmp = 0;

	/* Response Type check */
	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		tmp |= CMD_SET_RTYP_NO;
		break;
	case MMC_RSP_R1:
	case MMC_RSP_R1B:
	case MMC_RSP_R3:
		tmp |= CMD_SET_RTYP_6B;
		break;
	case MMC_RSP_R2:
		tmp |= CMD_SET_RTYP_17B;
		break;
	default:
		pr_err(DRIVER_NAME": Not support type response.\n");
		break;
	}
	switch (opc) {
	/* RBSY */
	case MMC_SWITCH:
	case MMC_STOP_TRANSMISSION:
	case MMC_SET_WRITE_PROT:
	case MMC_CLR_WRITE_PROT:
	case MMC_ERASE:
	case MMC_GEN_CMD:
		tmp |= CMD_SET_RBSY;
		break;
	}
	/* WDAT / DATW */
	if (host->data) {
		tmp |= CMD_SET_WDAT;
		switch (host->bus_width) {
		case MMC_BUS_WIDTH_1:
			tmp |= CMD_SET_DATW_1;
			break;
		case MMC_BUS_WIDTH_4:
			tmp |= CMD_SET_DATW_4;
			break;
		case MMC_BUS_WIDTH_8:
			tmp |= CMD_SET_DATW_8;
			break;
		default:
			pr_err(DRIVER_NAME": Not support bus width.\n");
			break;
		}
	}
	/* DWEN */
	if (opc == MMC_WRITE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK)
		tmp |= CMD_SET_DWEN;
	/* CMLTE/CMD12EN */
	if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) {
		tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN;
		sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET,
					mrq->data->blocks << 16);
	}
	/* RIDXC[1:0] check bits */
	if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID ||
	    opc == MMC_SEND_CSD || opc == MMC_SEND_CID)
		tmp |= CMD_SET_RIDXC_BITS;
	/* RCRC7C[1:0] check bits */
	if (opc == MMC_SEND_OP_COND)
		tmp |= CMD_SET_CRC7C_BITS;
	/* RCRC7C[1:0] internal CRC7 */
	if (opc == MMC_ALL_SEND_CID ||
		opc == MMC_SEND_CSD || opc == MMC_SEND_CID)
		tmp |= CMD_SET_CRC7C_INTERNAL;

	return opc = ((opc << 24) | tmp);
}
static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
			    struct mmc_request *mrq)
{
	struct mmc_data *data = mrq->data;
	struct mmc_command *cmd = mrq->cmd;
	u32 opc = cmd->opcode;
	u32 tmp = 0;

	/* Response Type check */
	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		tmp |= CMD_SET_RTYP_NO;
		break;
	case MMC_RSP_R1:
	case MMC_RSP_R1B:
	case MMC_RSP_R3:
		tmp |= CMD_SET_RTYP_6B;
		break;
	case MMC_RSP_R2:
		tmp |= CMD_SET_RTYP_17B;
		break;
	default:
		dev_err(&host->pd->dev, "Unsupported response type.\n");
		break;
	}
	switch (opc) {
	/* RBSY */
	case MMC_SLEEP_AWAKE:
	case MMC_SWITCH:
	case MMC_STOP_TRANSMISSION:
	case MMC_SET_WRITE_PROT:
	case MMC_CLR_WRITE_PROT:
	case MMC_ERASE:
		tmp |= CMD_SET_RBSY;
		break;
	}
	/* WDAT / DATW */
	if (data) {
		tmp |= CMD_SET_WDAT;
		switch (host->bus_width) {
		case MMC_BUS_WIDTH_1:
			tmp |= CMD_SET_DATW_1;
			break;
		case MMC_BUS_WIDTH_4:
			tmp |= CMD_SET_DATW_4;
			break;
		case MMC_BUS_WIDTH_8:
			tmp |= CMD_SET_DATW_8;
			break;
		default:
			dev_err(&host->pd->dev, "Unsupported bus width.\n");
			break;
		}
		switch (host->timing) {
		case MMC_TIMING_UHS_DDR50:
			/*
			 * MMC core will only set this timing, if the host
			 * advertises the MMC_CAP_UHS_DDR50 capability. MMCIF
			 * implementations with this capability, e.g. sh73a0,
			 * will have to set it in their platform data.
			 */
			tmp |= CMD_SET_DARS;
			break;
		}
	}
	/* DWEN */
	if (opc == MMC_WRITE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK)
		tmp |= CMD_SET_DWEN;
	/* CMLTE/CMD12EN */
	if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) {
		tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN;
		sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET,
				data->blocks << 16);
	}
	/* RIDXC[1:0] check bits */
	if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID ||
	    opc == MMC_SEND_CSD || opc == MMC_SEND_CID)
		tmp |= CMD_SET_RIDXC_BITS;
	/* RCRC7C[1:0] check bits */
	if (opc == MMC_SEND_OP_COND)
		tmp |= CMD_SET_CRC7C_BITS;
	/* RCRC7C[1:0] internal CRC7 */
	if (opc == MMC_ALL_SEND_CID ||
		opc == MMC_SEND_CSD || opc == MMC_SEND_CID)
		tmp |= CMD_SET_CRC7C_INTERNAL;

	return (opc << 24) | tmp;
}
Beispiel #29
0
static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat)
{
	unsigned long flags;
	u32 imask;

	WARN_ON(host->cmd != NULL);
	host->cmd = cmd;

	/* Ensure, that clock are stopped else command programming and start fails */
	imxmci_stop_clock(host);

	if (cmd->flags & MMC_RSP_BUSY)
		cmdat |= CMD_DAT_CONT_BUSY;

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_R1: /* short CRC, OPCODE */
	case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */
		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1;
		break;
	case MMC_RSP_R2: /* long 136 bit + CRC */
		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2;
		break;
	case MMC_RSP_R3: /* short */
		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
		break;
	default:
		break;
	}

	if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) )
		cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */

	if ( host->actual_bus_width == MMC_BUS_WIDTH_4 )
		cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;

	MMC_CMD = cmd->opcode;
	MMC_ARGH = cmd->arg >> 16;
	MMC_ARGL = cmd->arg & 0xffff;
	MMC_CMD_DAT_CONT = cmdat;

	atomic_set(&host->stuck_timeout, 0);
	set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events);


	imask = IMXMCI_INT_MASK_DEFAULT;
	imask &= ~INT_MASK_END_CMD_RES;
	if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) {
		/*imask &= ~INT_MASK_BUF_READY;*/
		imask &= ~INT_MASK_DATA_TRAN;
		if ( cmdat & CMD_DAT_CONT_WRITE )
			imask &= ~INT_MASK_WRITE_OP_DONE;
		if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
			imask &= ~INT_MASK_BUF_READY;
	}

	spin_lock_irqsave(&host->lock, flags);
	host->imask = imask;
	MMC_INT_MASK = host->imask;
	spin_unlock_irqrestore(&host->lock, flags);

	dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n",
		cmd->opcode, cmd->opcode, imask);

	imxmci_start_clock(host);
}
Beispiel #30
0
static void sslsd_request(struct mmc_host *mmc, struct mmc_request *req)
{
	sslsd_host			*host = mmc_priv(mmc);
	struct mmc_command	*cmd = req->cmd;
	sd_cmd_p			c = &host->tcmd;
	struct mmc_data		*d;
	int					flag;
	unsigned long		iflags;

	if (!sdhc_is_in(&host->hw))
	{
		cmd->error = -ENOMEDIUM;
		mmc_request_done(mmc, req);
		return;
	}

	c->dat = 0;
	switch (mmc_resp_type(cmd))
	{
		case MMC_RSP_R1: /* & R5, R6 */
			flag = SDCMD_F_R1;
			break;

		case MMC_RSP_R1B: /* & R5b */
			flag = SDCMD_F_R1B;
			break;

		case MMC_RSP_R2:
			flag = SDCMD_F_R2;
			c->dat = &host->tdat;
			c->dat->buf = (uint8_t *)cmd->resp;
			break;

		case MMC_RSP_R3:
			flag = SDCMD_F_R3;
			break;

		default:
			flag = 0;
			break;
	}

	c->cmd = cmd->opcode;
	c->arg = cmd->arg;
	host->pcmd = cmd;

	d = cmd->data;
	if (d)
	{
		struct scatterlist	*sg;
		sd_dat_p			dat;

		if (d->flags & MMC_DATA_STREAM) 
		{
			/* not supported */
			cmd->error = -EINVAL;
			mmc_request_done(mmc, req);
			return;
		}

		flag |= SDCMD_F_DAT;
		if (d->flags & MMC_DATA_WRITE)
		{
			flag |= SDCMD_F_WR;
		}
		if (d->blocks > 1)
		{
			flag |= SDCMD_F_MULTI;
		}
#if SD_DMA
		if (host->hw.fdma)
		{
			flag |= SDCMD_F_DMA;
		}
#endif

		dat = c->dat = &host->tdat;
		dat->blk = d->blksz;
#if 1
		c->tout = (d->timeout_ns + 1000000 - 1) / 1000000 + 
			d->timeout_clks / (mmc->ios.clock / 1000);
#endif

		sg = d->sg;
		host->sg = sg;
		host->sgc = d->sg_len;
		host->sgn = sg + d->sg_len - 1;
		host->sgofs = 0;

#if SD_DMA && IO_MAP == 1
		if (flag & SDCMD_F_DMA)
		{
			int	count;

			count = dma_map_sg(mmc_dev(mmc), sg, d->sg_len, 
						(flag & SDCMD_F_WR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
			if (!count)
			{
				/* failed to map even 1 page */
				cmd->error = -ENOMEM;
				mmc_request_done(mmc, req);
				return;
			}
			if (count != d->sg_len)
			{
				/* not all pages got mapped */
				count = d->sg_len - count;
				host->sgc -= count;
				host->sgn -= count;
			}
		}
#endif
		if (req->stop)
		{
			flag |= SDCMD_F_STOP;
		}
		c->flag = flag;
		sslsd_map(sg, c, dat, 0);
		host->retry = 1;
	}
	else
	{
		c->flag = flag;
	}

//printk("sslsd: cmd info - cmd=%d arg=%08X flags=%02X\n", 
//cmd->opcode, cmd->arg, flag);

	/* 2 sec timeout */
	mod_timer(&host->timer, jiffies + 2 * HZ);
	local_irq_save(iflags);
	flag = sdhc_cmd(&host->hw, c);
	local_irq_restore(iflags);
	if (flag)
	{
		sslsd_cmd_done(host, c);
	}
}