⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc_protocol.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 4 页
字号:
	 */	memset(g_buffer, 0xFF, 512);	bus_width = host->bus_width;	if (bus_width == MSS_BUSWIDTH_1BIT)		goto exit;	else if (bus_width == MSS_BUSWIDTH_4BIT) {		card->bus_width = MSS_BUSWIDTH_4BIT;		g_buffer[0] = 0xa5; /* 0b10100101 */		g_buffer[1] = 0xFF; /* 0b11111111 */	}	else if (bus_width == MSS_BUSWIDTH_8BIT) {		card->bus_width = MSS_BUSWIDTH_8BIT;		g_buffer[0] = 0xaa; /* 0b10101010 */		g_buffer[1] = 0x55; /* 0b01010101 */	}	else		goto exit;		mss_set_buswidth(host, bus_width);		memset(llreq, 0x0, sizeof(struct mss_ll_request));	memset(cmd, 0x0, sizeof(struct mss_cmd));	memset(data, 0x0, sizeof(struct mss_data));	MSS_INIT_CMD(cmd, MMC_BUSTEST_W, 0, 0, MSS_RESPONSE_R1); 	MSS_INIT_DATA(data, 1, 512, MSS_DATA_WRITE, 1, &sg, 0); 	llreq->cmd = cmd;	llreq->data = data;	ret = mss_send_ll_req(host, &mmc_card->llreq);	/* 	 * FIXME: Monahans will result MSS_ERROR_FLASH, but it seems that the 	 * output is correct	 */	if (ret && ret != MSS_ERROR_FLASH && ret != MSS_ERROR_CRC)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret)		return ret;	mmc_card->state = CARD_STATE_BTST;	memset(g_buffer, 0xFF, 512);	memset(llreq, 0x0, sizeof(struct mss_ll_request));	memset(cmd, 0x0, sizeof(struct mss_cmd));	memset(data, 0x0, sizeof(struct mss_data));	MSS_INIT_CMD(cmd, MMC_BUSTEST_R, 0, 0, MSS_RESPONSE_R1); 	MSS_INIT_DATA(data, 1, 512, MSS_DATA_READ, 1, &sg, 0); 	llreq->cmd = cmd;	llreq->data = data;		/* 	 * FIXME: Monahans will result MSS_ERROR_CRC, but it seems that the 	 * output is correct	 */	ret = mss_send_ll_req(host, &mmc_card->llreq);	if (ret && ret != MSS_ERROR_CRC && ret != MSS_ERROR_FLASH)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret)		return ret;	if ((g_buffer[0] == 0x55/*0b01010101*/) && 		(g_buffer[1] == 0xaa/*0b10101010*/)) {		mmc_card->bus_width = MSS_BUSWIDTH_8BIT;	}	else if (g_buffer[0] == 0x5a /*0b01011010*/) {		mmc_card->bus_width = MSS_BUSWIDTH_4BIT;	}	else { 		mmc_card->bus_width = MSS_BUSWIDTH_1BIT;	}#else	mss_set_buswidth(host, MSS_BUSWIDTH_4BIT);	mmc_card->bus_width = MSS_BUSWIDTH_4BIT;	#endif	mmc_card->state = CARD_STATE_TRAN;		arg = mmc_make_cmd6_arg(0x3, 0xb7, mmc_card->bus_width, 0);	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SWITCH, arg, 			MSS_RESPONSE_R1B, 0);	if (ret)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret)		return ret;		card->bus_width = mmc_card->bus_width;#ifdef CONFIG_MMC_CEATA	if (card->card_type != MSS_CEATA_CARD) 		goto continue_not_ceata;	memset(g_buffer, 0x0, 16);#ifndef CEATA_CSS_MODE	g_buffer[CEATA_CONTROL] = 0x02; /* not using CSS */#endif	g_buffer[CEATA_COMMAND_STATUS] = CEATA_IDENTIFY_DATA;	sg.page = virt_to_page(g_buffer);	sg.offset = offset_in_page(g_buffer);	sg.length = 16;	memset(llreq, 0x0, sizeof(struct mss_ll_request));	memset(cmd, 0x0, sizeof(struct mss_cmd));	memset(data, 0x0, sizeof(struct mss_data));	MSS_INIT_CMD(cmd, CEATA_RW_MULTIPLE_REGISTER, 0x80000010, 0, 			MSS_RESPONSE_R1B); 	MSS_INIT_DATA(data, 1, 16, MSS_DATA_WRITE, 1, &sg, 0); 	llreq->cmd = cmd;	llreq->data = data;		ret = mss_send_ll_req(host, &mmc_card->llreq);	if (ret)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret)		return ret;	retries = 10;	do {		mdelay(200);		ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_FAST_IO, 				(mmc_card->rca << 16) + 				(CEATA_COMMAND_STATUS << 8), 				MSS_RESPONSE_R4, 0);		if (ret)			return ret;		ret = mmc_unpack_r4(cmd, &r4, mmc_card);		if (ret) {			return ret;		}		status = r4.read_reg_contents;	} while((status & 0x40) != 0x40 && retries--);	if (!retries)		return MSS_ERROR_TIMEOUT;	mss_set_clock(host, mmc_tran_speed(mmc_card->csd.tran_speed));	memset(g_buffer, 0x0, 512);	sg.page = virt_to_page(g_buffer);	sg.offset = offset_in_page(g_buffer);	sg.length = 512;	memset(llreq, 0x0, sizeof(struct mss_ll_request));	memset(cmd, 0x0, sizeof(struct mss_cmd));	memset(data, 0x0, sizeof(struct mss_data));	MSS_INIT_CMD(cmd, CEATA_RW_MULTIPLE_BLOCK, 0x1, 0, 			MSS_RESPONSE_R1B); 	MSS_INIT_DATA(data, 1, 512, MSS_DATA_READ, 1, &sg, 0); 	llreq->cmd = cmd;	llreq->data = data;		ret = mss_send_ll_req(host, &mmc_card->llreq);	if (ret)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret)		return ret;	mmc_unpack_ceata(g_buffer, &mmc_card->ceata);continue_not_ceata:#endif	/** 	 * use CMD6 to set high speed mode. arg:access=0b11, arg:index=0xb9, 	 * arg:value=1 according to card/controller high speed timing  	 * high speed mode for MMC-4.x compatible card.	 */	if (host->high_speed == MSS_HIGH_SPEED) {		mmc_make_cmd6_arg(0x3, 0xb9, 1, 0);		ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SWITCH, arg, 				MSS_RESPONSE_R1B, 0);		if (ret)			return ret;		ret = mmc_unpack_r1(cmd, &r1, mmc_card);		if (ret)			return ret;		memcpy(&ios, &host->ios, sizeof(struct mss_ios)); 		ios.high_speed = MSS_HIGH_SPEED;		ios.clock = MMC_CARD_CLOCK_FAST;		host->ops->set_ios(host, &ios);			if (host->ios.high_speed != MSS_HIGH_SPEED) {			u32 clock = mmc_tran_speed(mmc_card->csd.tran_speed);			mss_set_clock(host, clock);			}	}	else {		/* change to the highest speed in normal mode */		u32 clock = mmc_tran_speed(mmc_card->csd.tran_speed);		mss_set_clock(host, clock);	}			/** 	 * use CMD6 to set power class. arg:access=0b11, arg:index=0xbb, 	 * arg:value=card power class code according to card/controller supported 	 * power class. We read value from PWL_CL_ff_vvv and set it to POWER_CLASS	 * according to supported voltage and clock rate.	 */#if 0	/* Deselect the card */	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SELECT_CARD, 0, 			MSS_RESPONSE_R1B, 0);	if (ret)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret)		return ret;	mmc_card->state = CARD_STATE_STBY;#endifexit:	return MSS_ERROR_NONE;}static int mmc_read_write_entry(struct mss_card *card, int action, struct mss_rw_arg *arg, struct mss_rw_result *result){	struct mmc_card *mmc_card = card->prot_card;	struct mss_host *host;	struct mss_ios ios;	struct mmc_response_r1 r1;	struct mss_ll_request *llreq = &mmc_card->llreq;	struct mss_cmd *cmd = &mmc_card->cmd;	struct mss_data *data = &mmc_card->data;	int ret, retries = 4, clock;	u32 status = 0;	int access_mode_sector = 0;	u32 cmdarg, blklen, opcode, flags;#ifdef CONFIG_MMC_CEATA	char *g_buffer = mmc_card->buf;	struct scatterlist sg;	struct mmc_response_r4 r4;#endif	host = card->slot->host;	ret = mmc_get_status(card, &status);	if (ret)		return ret;	if (status & R1_CARD_IS_LOCKED)		return MSS_ERROR_LOCKED;	if (action == MSS_WRITE_MEM && host->ops->is_slot_wp && 			host->ops->is_slot_wp(card->slot))		return MSS_ERROR_WP;		if (mmc_card->state == CARD_STATE_STBY) {		ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SELECT_CARD, 				mmc_card->rca << 16, MSS_RESPONSE_R1, 0);		if (ret)			return ret;		ret = mmc_unpack_r1(cmd, &r1, mmc_card);		if (ret)			return ret;	}	mmc_card->state = CARD_STATE_TRAN;	mmc_fix_request_block_len(card, action, arg);	memcpy(&ios, &host->ios, sizeof(struct mss_ios)); #ifdef CONFIG_MMC_CEATA	if (card->card_type == MSS_CEATA_CARD) {		blklen = arg->block_len;		goto ceata;	}#endif	access_mode_sector = (mmc_card->access_mode == MMC_ACCESS_MODE_SECTOR)	       	&& host->high_capacity;		if (access_mode_sector) {		ios.access_mode = MSS_ACCESS_MODE_SECTOR;		cmdarg = arg->block;		blklen = arg->block_len;	}	else {		if (arg->block_len != mmc_card->block_len) {			ret = mss_send_simple_ll_req(host, llreq, cmd, 					MMC_SET_BLOCKLEN, arg->block_len, 					MSS_RESPONSE_R1, 0);			if (ret)				return ret;			ret = mmc_unpack_r1(cmd, &r1, mmc_card); 			if (ret)				return ret;			mmc_card->block_len = arg->block_len;		}		cmdarg = arg->block * arg->block_len;		blklen = arg->block_len;	}#ifdef CONFIG_MMC_CEATAceata:#endif	if (mmc_card->csd.spec_vers == CSD_SPEC_VERS_4 && host->high_speed) {		ios.high_speed = MSS_HIGH_SPEED;		ios.clock = MMC_CARD_CLOCK_FAST;	}	else {		ios.clock = mmc_tran_speed(mmc_card->csd.tran_speed);	}	host->ops->set_ios(host, &ios);read_write_entry:	memset(llreq, 0x0, sizeof(struct mss_ll_request));	memset(cmd, 0x0, sizeof(struct mss_cmd));	memset(data, 0x0, sizeof(struct mss_data));	llreq->cmd = cmd;	llreq->data = data;	#ifdef CONFIG_MMC_CEATA	if (card->card_type != MSS_CEATA_CARD) 		goto no_ceata;	memset(g_buffer, 0x0, 16);#ifndef CEATA_CSS_MODE	g_buffer[CEATA_CONTROL] = 0x02;#endif	g_buffer[CEATA_SECTOR_COUNT] = arg->nob;	g_buffer[CEATA_LBA_LOW] = (arg->block * blklen / 512) & 0xFF;	g_buffer[CEATA_LBA_MID] = ((arg->block * blklen / 512) & 0xFF00) >> 8;	g_buffer[CEATA_LBA_HIGH] = (arg->block * blklen / 512)  >> 16;	g_buffer[CEATA_DEVICE_HEAD] = 0x40;	g_buffer[CEATA_COMMAND_STATUS] = (action == MSS_READ_MEM) ? 		CEATA_READ_DMA_EXT : CEATA_WRITE_DMA_EXT;	dbg("LBA_LOW:0x%x, LBR_MID:0x%x, LBR_HI:0x%x\n", g_buffer[CEATA_LBA_LOW], g_buffer[CEATA_LBA_MID], g_buffer[CEATA_LBA_HIGH]);	sg.page = virt_to_page(g_buffer);	sg.offset = offset_in_page(g_buffer);	sg.length = 16;	MSS_INIT_CMD(cmd, CEATA_RW_MULTIPLE_REGISTER, 0x80000010, 0, 			MSS_RESPONSE_R1B); 	MSS_INIT_DATA(data, 1, 16, MSS_DATA_WRITE, 1, &sg, 0); 	ret = mss_send_ll_req(host, &mmc_card->llreq);	if (ret)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret)		return ret;	retries = 10;	do {		mdelay(200);		ret = mss_send_simple_ll_req(host, llreq, cmd, 				MMC_FAST_IO, (mmc_card->rca << 16) 				+ (CEATA_COMMAND_STATUS << 8), 				MSS_RESPONSE_R4, 0);		if (ret)			return ret;		ret = mmc_unpack_r4(cmd, &r4, mmc_card);		if (ret) {			return ret;		}		status = r4.read_reg_contents;	} while((status & 0x48) != 0x48 && retries--);	if (!retries)		return MSS_ERROR_TIMEOUT;	cmdarg = arg->nob;	if (action == MSS_WRITE_MEM)		cmdarg |= 1 << 31;	memset(llreq, 0x0, sizeof(struct mss_ll_request));	memset(cmd, 0x0, sizeof(struct mss_cmd));	memset(data, 0x0, sizeof(struct mss_data));	llreq->cmd = cmd;	llreq->data = data;	if (action == MSS_READ_MEM) {		flags = MSS_DATA_READ | MSS_DATA_MULTI;	}	else {		flags = MSS_DATA_WRITE | MSS_DATA_MULTI;	}	MSS_INIT_CMD(cmd, CEATA_RW_MULTIPLE_BLOCK, cmdarg, 0, 			MSS_RESPONSE_R1B);	MSS_INIT_DATA(data, arg->nob, blklen, flags, arg->sg_len, 			arg->sg, 0);	ret = mss_send_ll_req(host, &mmc_card->llreq);	if (ret)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret)		return ret;	retries = 10;	do {		mdelay(200);		ret = mss_send_simple_ll_req(host, llreq, cmd, 				MMC_FAST_IO, (mmc_card->rca << 16) 				+ (CEATA_COMMAND_STATUS << 8), 				MSS_RESPONSE_R4, 0);		if (ret)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -