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

📄 mmc_protocol.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 4 页
字号:
	u16 block_len = 0;	struct mmc_card *mmc_card = card->prot_card;	struct mss_host *host = card->slot->host;	switch(action) {		case MSS_DATA_READ:			block_len = 1 << mmc_card->csd.read_bl_len;			break;		case MSS_DATA_WRITE:			block_len = 1 << mmc_card->csd.write_bl_len;			break;		default:			return;	}	if (host->high_capacity 			&& mmc_card->access_mode == MMC_ACCESS_MODE_SECTOR			&& card->card_type == MSS_CEATA_CARD)		block_len = 512;		if (block_len < arg->block_len) {		int scale = arg->block_len / block_len;		arg->block_len	= block_len;		arg->block *= scale;		arg->nob *= scale;	}}/***************************************************************************** * *   protocol entry functions * ****************************************************************************/static u32 mmc_make_cmd6_arg(u8 access, u8 index, u8 value, u8 cmdset){        u32 ret;        ret = (access << 24) | (index << 16) | (value << 8) | cmdset;        return ret;}#if 0static int mmc_simple_ll_req(struct mss_host *host, struct mmc_card *mmc_card, u32 opcode, u32 arg, u32 rtype, u32 flags){	memset(&mmc_card->llreq, 0x0, sizeof(struct mss_ll_request));	memset(&mmc_card->cmd, 0x0, sizeof(struct mss_cmd));	mmc_card->cmd.opcode = opcode;	mmc_card->cmd.arg = arg;	mmc_card->cmd.rtype = rtype;	mmc_card->cmd.flags = flags;	mmc_card->llreq.cmd = &mmc_card->cmd;	return mss_send_ll_req(host, &mmc_card->llreq);}	#endifstatic int mmc_get_status(struct mss_card *card, u32 *status){	struct mmc_response_r1 r1;	struct mmc_card *mmc_card = card->prot_card;	struct mss_host *host = card->slot->host;	struct mss_ll_request *llreq = &mmc_card->llreq;	struct mss_cmd *cmd = &mmc_card->cmd;	int clock, ret, retries = 4;	clock = mmc_tran_speed(mmc_card->csd.tran_speed);	mss_set_clock(card->slot->host, clock);	while (retries--) {		ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SEND_STATUS, 				mmc_card->rca << 16, MSS_RESPONSE_R1, 0);		if (ret && !retries)			return ret;		else if (!ret) {			ret = mmc_unpack_r1(cmd, &r1, mmc_card);			if (ret) {				if (mmc_card->errno==MMC_ERROR_STATE_MISMATCH) {					mmc_card->state = 						R1_CURRENT_STATE(r1.status);					mmc_card->errno = MMC_ERROR_NONE;				}				else					return ret;			}			else 				break;		}		clock = host->ios.clock;		clock = clock >> 1;		if (clock < MMC_CARD_CLOCK_SLOW || retries == 1)			clock = MMC_CARD_CLOCK_SLOW;		mss_set_clock(host, clock);	}	*status = r1.status;		return MSS_ERROR_NONE; }static int mmc_recognize_card(struct mss_card *card){	struct mmc_response_r3 r3;	struct mmc_card *mmc_card = card->prot_card;	struct mss_ios ios;	struct mss_host *host = card->slot->host;	struct mss_ll_request *llreq = &mmc_card->llreq;	struct mss_cmd *cmd = &mmc_card->cmd;	int ret;	u32 ocr = host->vdd;	mmc_card->state = CARD_STATE_IDLE;	card->bus_width = MSS_BUSWIDTH_1BIT;	card->card_type = MSS_UNKNOWN_CARD;		memcpy(&ios, &host->ios, sizeof(struct mss_ios)); 	ios.bus_mode = MSS_BUSMODE_OPENDRAIN;	ios.clock = host->f_min;	ios.bus_width = MSS_BUSWIDTH_1BIT;	host->ops->set_ios(host, &ios);	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_GO_IDLE_STATE, 0, 			MSS_RESPONSE_NONE, MSS_CMD_INIT); 	/* dbg("Sending GO_IDLE cmd, ret:%d\n", ret); */	if (ret)		return ret;	if (host->high_capacity)		ocr |= MMC_ACCESS_MODE_SECTOR;	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SEND_OP_COND, ocr, 			MSS_RESPONSE_R3, 0); 	/* dbg("Sending SEND_OP_COND cmd, arg:0x%x\n, ret:%d", ocr, ret); */	if (ret)		return ret;		ret = mmc_unpack_r3(cmd, &r3, mmc_card); 	dbg("unapck ret %d, SEND_OP_COND ocr:0x%x", ret, r3.ocr);	if (!ret) {		if (r3.ocr & host->vdd) {			card->card_type = MSS_MMC_CARD;		} else {			printk(KERN_WARNING "uncompatible card\n");			card->card_type = MSS_UNCOMPATIBLE_CARD;			}		return ret;	}	card->card_type = MSS_UNKNOWN_CARD;	return MSS_ERROR_NONE;}static int mmc_card_init(struct mss_card *card){	struct mmc_response_r3 r3;	struct mmc_response_r1 r1;	struct mmc_response_r4 r4;	struct mmc_cid cid;	struct mmc_card *mmc_card = card->prot_card;	struct mss_ios ios;	struct mss_host *host;	struct mss_ll_request *llreq = &mmc_card->llreq;	struct mss_cmd *cmd = &mmc_card->cmd;	struct mss_data *data = &mmc_card->data;	int ret;	u8 *g_buffer;	u32 ocr, arg, bus_width;	struct scatterlist sg;#ifdef CONFIG_MMC_CEATA	u32 status, retries = 10;#endif       	host = card->slot->host;	ocr = host->vdd;	mmc_card->state = CARD_STATE_IDLE;	card->bus_width = MSS_BUSWIDTH_1BIT;		memcpy(&ios, &host->ios, sizeof(struct mss_ios)); 	ios.bus_mode = MSS_BUSMODE_OPENDRAIN;	ios.bus_width = MSS_BUSWIDTH_1BIT;	ios.clock = host->f_min;	host->ops->set_ios(host, &ios);	/* dbg("Sending GO_IDLE cmd, ret:%d\n", ret); */	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_GO_IDLE_STATE, 0, 			MSS_RESPONSE_NONE, MSS_CMD_INIT); 	if (ret)		return ret;	if (host->high_capacity)		ocr |= MMC_ACCESS_MODE_SECTOR;	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SEND_OP_COND, ocr, 			MSS_RESPONSE_R3, 0); 	/* dbg("Sending SEND_OP_COND cmd, arg:0x%x\n, ret:%d", ocr, ret); */	if (ret)		return ret;		ret = mmc_unpack_r3(cmd, &r3, mmc_card);	/* dbg("unapck ret %d, SEND_OP_COND ocr:0x%x", ret, r3.ocr); */	if (ret) {		return ret;	}	while (!(r3.ocr & MMC_CARD_BUSY)) {		mdelay(20);		ret = mss_send_simple_ll_req(host, llreq, cmd, 				MMC_SEND_OP_COND, ocr, MSS_RESPONSE_R3, 0); 		if (ret)			return ret;		ret = mmc_unpack_r3(cmd, &r3, mmc_card);		if (ret) {			return ret;		}	}	mmc_card->vdd = r3.ocr & MMC_VDD_MASK;	mmc_card->access_mode = r3.ocr & MMC_ACCESS_MODE_MASK;	mmc_card->state = CARD_STATE_READY;		ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_ALL_SEND_CID, 0, 			MSS_RESPONSE_R2_CID, 0); 	/* dbg("Sending MMC_ALL_SEND_CID cmd, arg:0x%x\n, ret:%d", 0, ret); */	if (ret)		return ret;	memset(&cid, 0x0, sizeof(struct mmc_cid));	ret = mmc_unpack_cid(cmd, &cid, mmc_card);	if (ret)		return ret;	/* Not first init */	if (mmc_card->cid.mid != 0) {		/* Card is changed */		if (mmc_card->cid.mid != cid.mid || mmc_card->cid.oid != cid.oid				|| mmc_card->cid.prv != cid.prv 				|| mmc_card->cid.psn != cid.psn				|| mmc_card->cid.mdt != cid.mdt				|| memcmp(mmc_card->cid.pnm, cid.pnm, 6))			return MSS_ERROR_MISMATCH_CARD;	}	else 		memcpy(&mmc_card->cid, &cid, sizeof(struct mmc_cid));		mmc_card->state = CARD_STATE_IDENT;	mss_set_busmode(host, MSS_BUSMODE_PUSHPULL);	mmc_card->rca = MMC_SLOT_RCA(card->slot);	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SET_RELATIVE_ADDR, 			mmc_card->rca << 16, MSS_RESPONSE_R1, 0); 	/* dbg("Sending SET_REL_ADDR cmd, arg:0x%x\n, ret:%d", 			mmc_card->rca << 16, ret); */	if (ret)		return ret;    	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	if (ret) {		return ret;	}  	mmc_card->state = CARD_STATE_STBY;	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SEND_CSD, 			mmc_card->rca << 16, MSS_RESPONSE_R2_CSD, 0);	/* dbg("Sending MMC_SEND_CSD cmd, arg:0x%x\n, ret:%d", 			mmc_card->rca << 16, ret); */	if (ret)		return ret;	ret = mmc_unpack_csd(cmd, &mmc_card->csd, mmc_card);	if (ret) {		return ret;	}#ifdef CONFIG_MMC_CEATA	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_FAST_IO, 			(mmc_card->rca << 16) + (CEATA_LBA_MID << 8), 			MSS_RESPONSE_R4, 0);	if (ret == MSS_ERROR_TIMEOUT)		goto no_ceata;	if (ret)		return ret;	ret = mmc_unpack_r4(cmd, &r4, mmc_card);	if (ret) {		return ret;	}	if (r4.read_reg_contents != 0xCE)		goto no_ceata;		card->card_type = MSS_CEATA_CARD;	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_FAST_IO, 			(mmc_card->rca << 16) + (CEATA_LBA_HIGH << 8), 			MSS_RESPONSE_R4, 0);	if (ret)		return ret;	ret = mmc_unpack_r4(cmd, &r4, mmc_card);	if (ret) {		return ret;	}	if (r4.read_reg_contents != 0xAA) {		return MSS_ERROR_WRONG_CARD_TYPE;	}	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;no_ceata:#endif		/*	 * if it is MMC4.x-compatible card and how many bits are working.	 */	if (mmc_card->csd.spec_vers != CSD_SPEC_VERS_4 			|| host->mmc_spec != MSS_MMC_SPEC_40_42) 		goto exit;	g_buffer = mmc_card->buf;	ret = mss_send_simple_ll_req(host, llreq, cmd, MMC_SELECT_CARD, 			mmc_card->rca << 16, MSS_RESPONSE_R1B, 0);	if (ret)		return ret;	ret = mmc_unpack_r1(cmd, &r1, mmc_card);	/* 	 * If CEATA is enabled, no-CEATA card will get 	 * MMC_ERROR_ILLEGAL_COMMAND because it recieves the FAST_IO command 	 * that it does not support 	 */#ifdef CONFIG_MMC_CEATA	if (ret && mmc_card->errno != MMC_ERROR_ILLEGAL_COMMAND)#else	if (ret)#endif		return ret;	mmc_card->state = CARD_STATE_TRAN;	/*	 * set 1-bus mode in init. arg:access=0b11, arg:index=0xb7, arg:value=0	 * or CMD8 will not be responded with 1-bit/controller and 4-bit/card	 * dev->bus_mode should be MSS_1_BIT before next command	 * buffer = NULL;	 */	arg = mmc_make_cmd6_arg(0x3, 0xb7, 0, 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 = MSS_BUSWIDTH_1BIT;	mss_set_buswidth(host, MSS_BUSWIDTH_1BIT);	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, MMC_SEND_EXT_CSD, 0, 0, MSS_RESPONSE_R1); 	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_ext_csd(g_buffer, &mmc_card->ext_csd);	if (ret)		return ret;/*  * Monahans MMC controller does not support BUS_R and BUS_W command correctly, * so we direclty set the card bus width to be 4 bit  */	#if 0	/*	 *  use CMD19/CMD14 (BUSTEST_W/BUSTEST_R) to test supported bus mode.

⌨️ 快捷键说明

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