Ejemplo n.º 1
0
Archivo: sd_boot.c Proyecto: ykli/misc
static u8* mmc_cmd(u16 cmd, u32 arg, u32 cmdat, u16 rtype)
{
	static u8 resp[6];
	int i;

	REG_MSC_CMD(ctl_num) = cmd;
	REG_MSC_ARG(ctl_num) = arg;
	REG_MSC_CMDAT(ctl_num) = cmdat;

	jz_mmc_start();
	/* cmd0 with arg 0xfffffffa and set the MSC_CMDAT_BOOT_MODE_A can not wait for MSC_STAT_END_CMD_RES set */
	if ((arg == 0xfffffffa) && (cmd == 0) && (cmdat & MSC_CMDAT_BOOT_MODE_A))
		return 0;

	while (!(REG_MSC_STAT(ctl_num) & MSC_STAT_END_CMD_RES))
		;

	REG_MSC_IREG(ctl_num) = MSC_IREG_END_CMD_RES;

	if (rtype == MSC_CMDAT_RESPONSE_NONE)
		return 0;

	for (i = 2; i >= 0; i--) {
		u16 res_fifo = REG_MSC_RES(ctl_num);
		int offset = i << 1;

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

	return resp;
}
Ejemplo 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;

	/* mask interrupts */
	REG_MSC_IMASK(MSC_ID) = 0xffff;

	/* clear status */
	REG_MSC_IREG(MSC_ID) = 0xffff;

	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(MSC_ID) = cmd->opcode;

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

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

#elif defined CONFIG_JZ4750_MSC0_BUS_8
	if (cmd->opcode == 6) {
		/* set  8 bit mmc card bus*/
		if (cmd->arg == 0x3b70101) 
			REG_MSC_ARG(MSC_ID) = 0x3b70201;
		else
			REG_MSC_ARG(MSC_ID) = cmd->arg;
					
	} else
		REG_MSC_ARG(MSC_ID) = cmd->arg;
#else
	REG_MSC_ARG(MSC_ID) = cmd->arg;
#endif /* CONFIG_JZ4750_MSC0_BUS_1 */
#else 
#ifdef CONFIG_JZ4750_MSC1_BUS_1
	if (cmd->opcode == 6) {
		/* set  1 bit sd card bus*/
		if (cmd->arg ==2)  
			REG_MSC_ARG(MSC_ID) = 0;

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

#else
	REG_MSC_ARG(MSC_ID) = cmd->arg;
#endif /* CONFIG_JZ4750_MSC1_BUS_1 */
#endif /* CONFIG_MSC0_JZ4750*/

	/* Set command */
	REG_MSC_CMDAT(MSC_ID) = cmdat;

	/* Send command */
	jz_mmc_start_op();

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

	REG_MSC_IREG(MSC_ID) = MSC_IREG_END_CMD_RES;	/* clear irq flag */
	if (cmd->opcode == 12) {
		while (timeout-- && !(REG_MSC_IREG(MSC_ID) & MSC_IREG_PRG_DONE))
			;
		REG_MSC_IREG(MSC_ID) = 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(MSC_ID);
	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
	}