コード例 #1
0
ファイル: sd_boot.c プロジェクト: 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;
}
コード例 #2
0
ファイル: sd_boot.c プロジェクト: ykli/misc
int mmc_block_readp(u32 size, u32 *dst)
{
	u32 nob, cnt, stat;

	nob = size / 64;

	xtimeout(50*1000,1);

	while (!(REG_MSC_STAT(ctl_num) & MSC_STAT_BAR))
		if (!xtimeout(51*1000, 0))
			goto err;

	if (REG_MSC_STAT(ctl_num) & MSC_STAT_BAE)
			goto err;

	for (; nob > 0; nob--) {
		while(1){
			stat = REG_MSC_STAT(ctl_num);

			if (stat & (MSC_STAT_TIME_OUT_READ | MSC_STAT_CRC_READ_ERROR | MSC_STAT_BCE))
				goto err;

			if(!(stat & MSC_STAT_DATA_FIFO_EMPTY))
				break;
		}

		cnt = 16;		//16 words
		while (cnt--) {
			while (!(REG_MSC_IREG(ctl_num) & MSC_IREG_RXFIFO_RD_REQ))
				;
			*dst = REG_MSC_RXFIFO(ctl_num);
			if (size - (nob * 64) >= redundancy_size)
				dst++;
		}
	}

	return 0;
err:
	if (REG_MSC_STAT(ctl_num) & MSC_STAT_BCE)
		REG_MSC_CMDAT(ctl_num) |= (MSC_CMDAT_DIS_BOOT);

	return 1;
}
コード例 #3
0
static void jz_mmc_send_pio(struct jz_mmc_host *host)
{

	struct mmc_data *data = 0;
	int sg_len, max, count = 0;
	u32 *wbuf = 0;
	struct scatterlist *sg;
	unsigned int nob;

	data = host->mrq->data;
	nob = data->blocks;

	REG_MSC_NOB(MSC_ID) = nob;
	REG_MSC_BLKLEN(MSC_ID) = data->blksz;

	/* This is the pointer to the data buffer */
	sg = &data->sg[host->pio.index];
	wbuf = sg_virt(sg) + host->pio.offset;

	/* This is the space left inside the buffer */
	sg_len = data->sg[host->pio.index].length - host->pio.offset;

	/* Check to if we need less then the size of the sg_buffer */
	max = (sg_len > host->pio.len) ? host->pio.len : sg_len;
	max = max / 4;
	for(count = 0; count < max; count++ ) {
		while (REG_MSC_STAT(MSC_ID) & MSC_STAT_DATA_FIFO_FULL)
				;
		REG_MSC_TXFIFO(MSC_ID) = *wbuf++;
	}

	host->pio.len -= count;
	host->pio.offset += count;

	if (count == sg_len) {
		host->pio.index++;
		host->pio.offset = 0;
	}
}
コード例 #4
0
static void jz_mmc_receive_pio(struct jz_mmc_host *host)
{

	struct mmc_data *data = 0;
	int sg_len = 0, max = 0, count = 0;
	u32 *buf = 0;
	struct scatterlist *sg;
	unsigned int nob;

	data = host->mrq->data;
	nob = data->blocks;
	REG_MSC_NOB(MSC_ID) = nob;
	REG_MSC_BLKLEN(MSC_ID) = data->blksz;

	max = host->pio.len;
	if (host->pio.index < host->dma.len) {
		sg = &data->sg[host->pio.index];
		buf = sg_virt(sg) + host->pio.offset;

		/* This is the space left inside the buffer */
		sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset;
		/* Check to if we need less then the size of the sg_buffer */
		if (sg_len < max) max = sg_len;
	}
	max = max / 4;
	for(count = 0; count < max; count++) {
		while (REG_MSC_STAT(MSC_ID) & MSC_STAT_DATA_FIFO_EMPTY)
			;
		*buf++ = REG_MSC_RXFIFO(MSC_ID);
	} 
	host->pio.len -= count;
	host->pio.offset += count;

	if (sg_len && count == sg_len) {
		host->pio.index++;
		host->pio.offset = 0;
	}
}
コード例 #5
0
ファイル: sd_boot.c プロジェクト: ykli/misc
int mmc_block_read(u32 size, u32 *dst)
{
	u8 *resp;
	u32 nob, cnt, stat;

	resp = mmc_cmd(16, 0x200, 0x1, MSC_CMDAT_RESPONSE_R1);

	REG_MSC_BLKLEN(ctl_num) = 0x200;
	REG_MSC_NOB(ctl_num) = size / 512;

	resp = mmc_cmd(18, 0x0, 0x9, MSC_CMDAT_RESPONSE_R1);	//more than 16
	nob = size / 64;

	for (; nob > 0; nob--) {
		while(1){
			stat = REG_MSC_STAT(ctl_num);
			if (stat & (MSC_STAT_TIME_OUT_READ | MSC_STAT_CRC_READ_ERROR)) {
				goto err;
			}

			if(!(stat & MSC_STAT_DATA_FIFO_EMPTY))
				break;
		}

		cnt = 16;		//16 words
		while (cnt--) {
			while (!(REG_MSC_IREG(ctl_num) & MSC_IREG_RXFIFO_RD_REQ))
				;
			*dst = REG_MSC_RXFIFO(ctl_num);
			if (size - (nob * 64) >= redundancy_size)
				dst++;
		}
	}
	resp = mmc_cmd(12, 0, 0x1, MSC_CMDAT_RESPONSE_R1);
	return 0;
err:
	return 1;
}
コード例 #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;

	/* 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
	}
コード例 #7
0
ファイル: sd_boot.c プロジェクト: ykli/misc
static inline void wait_prog_done(void)
{
	while (!(REG_MSC_STAT(ctl_num) & MSC_STAT_PRG_DONE))
		;
	REG_MSC_IREG(ctl_num) = MSC_IREG_PRG_DONE;
}