Esempio n. 1
0
static u8 * mmc_cmd(u16 cmd, unsigned int arg, unsigned int cmdat, u16 rtype)
{
    u32 timeout = 0x7fffff;
    int words, i;

    clear_resp();
    jz_mmc_stop_clock();

    REG_MSC_CMD   = cmd;
    REG_MSC_ARG   = arg;
    REG_MSC_CMDAT = cmdat;

    REG_MSC_IMASK = ~MSC_IMASK_END_CMD_RES;
    jz_mmc_start_clock();

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

    REG_MSC_IREG = MSC_IREG_END_CMD_RES;

    switch (rtype) {
    case MSC_CMDAT_RESPONSE_R1:
    case MSC_CMDAT_RESPONSE_R3:
    case MSC_CMDAT_RESPONSE_R6:
        words = 3;
        break;
    case MSC_CMDAT_RESPONSE_R2:
        words = 8;
        break;
    default:
        return 0;
    }
    for (i = words-1; i >= 0; i--) {
        u16 res_fifo = REG_MSC_RES;
        int offset = i << 1;

        resp[offset] = ((u8 *)&res_fifo)[0];
        resp[offset+1] = ((u8 *)&res_fifo)[1];

    }
    return resp;
}
Esempio n. 2
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
	}