Example #1
0
static void jz_mmc_finish_request(struct jz_mmc_host *host, struct mmc_request *mrq)
{
	jz_mmc_stop_clock();
	host->mrq = NULL;
	host->cmd = NULL;
	host->data = NULL;
	mmc_request_done(host->mmc, mrq);
}
Example #2
0
/* Select the MMC clock frequency */
static int jz_mmc_set_clock(u32 rate)
{
	int clkrt;

	jz_mmc_stop_clock();
	__cpm_select_msc_clk(1);	/* select clock source from CPM */
	clkrt = jz_mmc_calc_clkrt(1, rate);
	REG_MSC_CLKRT = clkrt;
	return MMC_NO_ERROR;
}
Example #3
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;
}
Example #4
0
static int mmc_block_writem(u32 src, u32 num, u8 *dst)
{
    u8 *resp;
    u32 stat, timeout, data, cnt, wait, nob, i, j;
    u32 *wbuf = (u32 *)dst;

    resp = mmc_cmd(16, 0x200, 0x1, MSC_CMDAT_RESPONSE_R1);
    REG_MSC_BLKLEN = 0x200;
    REG_MSC_NOB = num / 512;

    if (highcap)
        resp = mmc_cmd(25, src, 0x19 | (BUS_WIDTH << 9), MSC_CMDAT_RESPONSE_R1); // for sdhc card
    else
        resp = mmc_cmd(25, src * 512, 0x19 | (BUS_WIDTH << 9), MSC_CMDAT_RESPONSE_R1);
    nob  = num / 512;
    timeout = 0x3ffffff;
    //serial_puts("nob ==w===");serial_put_hex(nob);
    //serial_dump_data(dst, 16);
    for (i = 0; i < nob; i++) {
        timeout = 0x3FFFFFF;
        while (timeout) {
            timeout--;
            stat = REG_MSC_STAT;

            if (stat & (MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_WRITE_ERROR_NOSTS))
                return -1;
            else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) {
                /* Ready to write data */
                break;
            }

            wait = 336;
            while (wait--)
                ;
        }
        if (!timeout)
            return -1;

        /* Write data to TXFIFO */
        cnt = 128;
        while (cnt) {
            //stat = REG_MSC_STAT;
            //serial_puts("stat ==write===");serial_put_hex(stat);
            while(!(REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ))
                ;
            for (j=0; j<16; j++)
            {
                //serial_put_hex(*wbuf);
                REG_MSC_TXFIFO = *wbuf++;
                cnt--;
            }
        }
    }
#if 0
    while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)) ;
    REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE;	/* clear status */

    resp = mmc_cmd(12, 0, 0x441, MSC_CMDAT_RESPONSE_R1);
    while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE)) ;
    REG_MSC_IREG = MSC_IREG_PRG_DONE;	/* clear status */

#else
    while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)) ;
    REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE;	/* clear status */

    while (!(REG_MSC_STAT & MSC_STAT_PRG_DONE)) ;
    REG_MSC_IREG = MSC_IREG_PRG_DONE;	/* clear status */

    resp = mmc_cmd(12, 0, 0x441, MSC_CMDAT_RESPONSE_R1);
    do {
        resp = mmc_cmd(13, rca, 0x1, MSC_CMDAT_RESPONSE_R1); // for sdhc card
    } while(!(resp[2] & 0x1));   //wait the card is ready for data

#endif
    jz_mmc_stop_clock();
    //return src+nob;
    return 0;
}
Example #5
0
static int mmc_block_readm(u32 src, u32 num, u8 *dst)
{
    u8 *resp;
    u32 stat, timeout, data, cnt, wait, nob;

    resp = mmc_cmd(16, 0x200, 0x401, MSC_CMDAT_RESPONSE_R1);
    REG_MSC_BLKLEN = 0x200;
    REG_MSC_NOB = num / 512;

    if (highcap)
        resp = mmc_cmd(18, src,  0x10409, MSC_CMDAT_RESPONSE_R1); // for sdhc card
    else
        resp = mmc_cmd(18, src * 512, 0x10409, MSC_CMDAT_RESPONSE_R1);
    nob  = num / 512;
    //serial_puts("nob ==r===");serial_put_hex(nob);
    //serial_puts("src ==r===");serial_put_hex(src);
    for (nob; nob >= 1; nob--) {
        timeout = 0x7ffffff;
        while (timeout) {
            timeout--;
            stat = REG_MSC_STAT;

            if (stat & MSC_STAT_TIME_OUT_READ) {
                serial_puts("\n MSC_STAT_TIME_OUT_READ\n\n");
                return -1;
            }
            else if (stat & MSC_STAT_CRC_READ_ERROR) {
                serial_puts("\n MSC_STAT_CRC_READ_ERROR\n\n");
                return -1;
            }
            else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY)) {
                /* Ready to read data */
                break;
            }
            wait = 336;
            while (wait--)
                ;
        }
        if (!timeout) {
            serial_puts("\n mmc/sd read timeout\n");
            return -1;
        }

        /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */
        cnt = 128;
        while (cnt) {
            while (cnt && (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY))
                ;
            cnt --;
            data = REG_MSC_RXFIFO;
            {
                *dst++ = (u8)(data >> 0);
                *dst++ = (u8)(data >> 8);
                *dst++ = (u8)(data >> 16);
                *dst++ = (u8)(data >> 24);
            }
        }
    }
#if defined(MSC_STAT_AUTO_CMD_DONE)
    while(!(REG_MSC_STAT & MSC_STAT_AUTO_CMD_DONE));
#else
    resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1);
    while (!(REG_MSC_STAT & MSC_STAT_DATA_TRAN_DONE));
#endif
    jz_mmc_stop_clock();
    return 0;
}
Example #6
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
	}
Example #7
0
static int mmc_block_writem(u32 src, u32 num, u8 *dst)
{
	u8 *resp;
	u32 stat, timeout, cnt, nob, sorm;
	u32 *wbuf = (u32 *)dst;

	resp = mmc_cmd(16, 0x200, 0x401, MSC_CMDAT_RESPONSE_R1);
	REG_MSC_BLKLEN = 0x200;
	REG_MSC_NOB = num / 512;
	nob  = num / 512;

	if (nob == 1) {
		if (highcap)
			resp = mmc_cmd(24, src, 0x419, MSC_CMDAT_RESPONSE_R1);
		else
			resp = mmc_cmd(24, src * 512, 0x419, MSC_CMDAT_RESPONSE_R1);

		sorm = 0;
	} else {
		if (highcap)
			resp = mmc_cmd(25, src, 0x419, MSC_CMDAT_RESPONSE_R1); // for sdhc card
		else
			resp = mmc_cmd(25, src * 512, 0x419, MSC_CMDAT_RESPONSE_R1);

		sorm = 1;
	}

	for (nob; nob >= 1; nob--) {
		timeout = 0x3FFFFFF;

		while (timeout) {
			timeout--;
			stat = REG_MSC_STAT;
			if (stat & (MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_WRITE_ERROR_NOSTS)) {
				serial_puts("\n MSC_STAT_CRC_WRITE_ERROR\n\n");
				return -1;
			}
			else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) {
				/* Ready to write data */
				break;
			}

			udelay(1);
		}

		if (!timeout)
			return -1;

		/* Write data to TXFIFO */
		cnt = 128;
		while (cnt) {
			while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL)
				;
			REG_MSC_TXFIFO = *wbuf++;
			cnt--;
		}
	}

	if (sorm)
		resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1);

	while (!(REG_MSC_STAT & MSC_STAT_DATA_TRAN_DONE))
		;
	
	REG_MSC_IREG |= MSC_IREG_DATA_TRAN_DONE;	

	while (!(REG_MSC_STAT & MSC_STAT_PRG_DONE))
		;
	REG_MSC_IREG |= MSC_IREG_PRG_DONE;	

	jz_mmc_stop_clock();
	return 0;
}
Example #8
0
static int mmc_block_readm(u32 src, u32 num, u8 *dst)
{
	u8 *resp;
	u32 stat, timeout, data, cnt, nob, sorm;

	resp = mmc_cmd(16, 0x200, 0x401, MSC_CMDAT_RESPONSE_R1);
	REG_MSC_BLKLEN = 0x200;
	REG_MSC_NOB = num / 512;
	nob  = num / 512;

	if (nob == 1) {
		if (highcap)
			resp = mmc_cmd(17, src, 0x409, MSC_CMDAT_RESPONSE_R1);
		else
			resp = mmc_cmd(17, src * 512, 0x409, MSC_CMDAT_RESPONSE_R1);
			
		sorm = 0;
	} else {
		if (highcap)
			resp = mmc_cmd(18, src, 0x409, MSC_CMDAT_RESPONSE_R1);
		else
			resp = mmc_cmd(18, src * 512, 0x409, MSC_CMDAT_RESPONSE_R1);

		sorm = 1;
	}

	for (nob; nob >= 1; nob--) {
		timeout = 0x3ffffff;

		while (timeout) {
			timeout--;
			stat = REG_MSC_STAT;
			if (stat & MSC_STAT_TIME_OUT_READ) {
				serial_puts("\n MSC_STAT_TIME_OUT_READ\n\n");
				return -1;
			}
			else if (stat & MSC_STAT_CRC_READ_ERROR) {
				serial_puts("\n MSC_STAT_CRC_READ_ERROR\n\n");
				return -1;
			}
			else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY)) {
				/* Ready to read data */
				break;
			}
			udelay(1);
		}
		if (!timeout) {
			serial_puts("\n mmc/sd read timeout\n");
			return -1;
		}

		/* Read data from RXFIFO. It could be FULL or PARTIAL FULL */
		cnt = 128;
		while (cnt) {
			while (cnt && (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY))
				;
			cnt --;

			data = REG_MSC_RXFIFO;
			{
				*dst++ = (u8)(data >> 0);
				*dst++ = (u8)(data >> 8);
				*dst++ = (u8)(data >> 16);
				*dst++ = (u8)(data >> 24);
			}
		}
	}

	if (sorm)
		resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1);

	while (!(REG_MSC_STAT & MSC_STAT_DATA_TRAN_DONE))
		;
	
	REG_MSC_IREG |= MSC_IREG_DATA_TRAN_DONE;	

	jz_mmc_stop_clock();
	return 0;
}