Beispiel #1
0
int emmc_boot(void)
{
	int ret;

	current_boot = EMMC_BOOT;
	ctl_num = 0;

	sd_init();
	REG_MSC_CLKRT(ctl_num) = 1;
	REG_MSC_LPM(ctl_num) = 1;

	/* cmd12 reset when we reading or writing from the card, send this cmd */
	mmc_cmd(12, 0, 0x1, MSC_CMDAT_RESPONSE_R1);

	mmc_cmd(0, 0xf0f0f0f0, 0x80, MSC_CMDAT_RESPONSE_NONE);

	REG_MSC_BLKLEN(ctl_num) = 0x200;
	REG_MSC_NOB(ctl_num) = (SPL_SIZE + redundancy_size) / 512;
	mmc_cmd(0, 0xfffffffa, ((MSC_CMDAT_INIT) | (MSC_CMDAT_EXP_BOOT_ACK) | (MSC_CMDAT_BOOT_MODE_A) | (MSC_CMDAT_DATA_EN)), MSC_CMDAT_RESPONSE_NONE);

	ret = mmc_block_readp(SPL_SIZE + redundancy_size, (u32 *)start_addr);

	if(!ret){
		mmc_cmd(0, 0, 0x0, MSC_CMDAT_RESPONSE_NONE);

		if (!(REG32(start_addr) == 0x4d53504c)){
			return sd_boot(1);
		}

		return xfer_d2i(start_addr + jump_offset, SPL_SIZE);
	}else{
		return error_handler(current_boot);
	}
}
Beispiel #2
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;
	}
}
Beispiel #3
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;
	}
}
Beispiel #4
0
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;
}
Beispiel #5
0
/* Prepare DMA to start data transfer from the MMC card */
static void jz_mmc_tx_setup_data(struct jz_mmc_host *host,
				 struct mmc_data *data)
{
	unsigned int nob = data->blocks;
	int channeltx = txdmachan;
	int i;
	u32 size;

	if (data->flags & MMC_DATA_STREAM)
		nob = 0xffff;

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

	if (data->flags & MMC_DATA_READ) {
		host->dma.dir = DMA_FROM_DEVICE;
	} else {
		host->dma.dir = DMA_TO_DEVICE;
	}

	host->dma.len =
		dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
			   host->dma.dir);

	for (i = 0; i < host->dma.len; i++) {
		host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]);
		host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]);
		dma_cache_wback_inv((unsigned long)
				    CKSEG0ADDR(sg_dma_address(data->sg)) +
				    data->sg->offset,
				    host->sg_cpu[i].dcmd);
		jz_mmc_start_dma(channeltx, host->sg_cpu[i].dtadr,
				 host->sg_cpu[i].dcmd, DMA_MODE_WRITE);
	}
}