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

📄 sdio_protocol.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 3 页
字号:
 * *   protocol entry functions * ****************************************************************************/static int sdio_recognize_card(struct mss_card *card){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r4 r4;	struct mss_ios ios;	int ret;	card->card_type = MSS_UNKNOWN_CARD;	sdio_card->state = CARD_STATE_INIT;	card->bus_width = MSS_BUSWIDTH_1BIT;		memcpy(&ios, &host->ios, sizeof(struct mss_ios)); 	ios.clock = host->f_min;	ios.bus_width = MSS_BUSWIDTH_1BIT;	host->ops->set_ios(host, &ios);	/* check if a sdio card, need not send CMD0 to reset for SDIO card */	ret = mss_send_simple_ll_req(host, llreq, cmd, IO_SEND_OP_COND, 			0, MSS_RESPONSE_R4, 0);	if (ret)		return ret;	ret = sdio_unpack_r4(cmd, &r4, sdio_card);  	if (ret)		return ret;	sdio_card->func_num = r4.func_num;	sdio_card->mem_present = r4.mem_present;	if (!r4.func_num)		return MSS_ERROR_NONE;	/*  maybe COMBO_CARD. but we can return SDIO_CARD first, 	 *  in sdio_card_init, we will judge further.	 */	if(r4.ocr & host->vdd) {		card->card_type = MSS_SDIO_CARD;	} else {		printk(KERN_WARNING "uncompatible card\n");		card->card_type = MSS_UNCOMPATIBLE_CARD;	}		return MSS_ERROR_NONE;}static int sdio_card_init(struct mss_card *card){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r1 r1;	struct sdio_response_r4 r4;	struct sdio_response_r6 r6;	struct mss_ios ios;	int ret, tmp, i;	u8 funcs;		/* It is better for sdio reset here to re-init */ 	if (card->state & MSS_CARD_REGISTERED) { 		sdio_reset(card); 		card->state &= ~MSS_CARD_INITED; 	}	sdio_card->state = CARD_STATE_INIT;	card->bus_width = MSS_BUSWIDTH_1BIT;		memcpy(&ios, &host->ios, sizeof(struct mss_ios)); 	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, IO_SEND_OP_COND, 			host->vdd, MSS_RESPONSE_R4, 0);	if (ret)		return ret;	ret = sdio_unpack_r4(cmd, &r4, sdio_card);	if (ret) 		return ret;		while (!r4.ready) {		mdelay(20);		ret = mss_send_simple_ll_req(host, llreq, cmd, IO_SEND_OP_COND, 				host->vdd, MSS_RESPONSE_R4, 0);		if (ret)			return ret;		ret = sdio_unpack_r4(cmd, &r4, sdio_card);		if (ret) 			return ret;	}		ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SET_RELATIVE_ADDR, 			0, MSS_RESPONSE_R6, 0);	if (ret)		return ret;    	ret = sdio_unpack_r6(cmd, &r6, sdio_card);	if (ret) 		return ret;	sdio_card->state = CARD_STATE_STBY;		sdio_card->rca = r6.rca;	ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SELECT_CARD, 			(sdio_card->rca) << 16, MSS_RESPONSE_R1B, 0);	if (ret)		return ret;	ret = sdio_unpack_r1(cmd, &r1, sdio_card);	if (ret)		return ret;	/** CARD_STATE_CMD */	//slot->state = CARD_STATE_CMD;	//send CMD53 to let DATA BUS FREE, since bus_suspend not supported, need not to do this	//arg = sdio_make_cmd53_arg(SDIO_READ, 0, 0, 0, 0, 1);	//mss_simple_cmd( dev, IO_RW_EXTENDED, arg, RESPONSE_R5);	/** CARD_STATE_TRAN */	sdio_card->state = CARD_STATE_CMD;	ret = get_sdio_cccr_info(card);	if (ret)		return ret;    dbg("bus_width is %d\n", host->bus_width);	if(host->bus_width == MSS_BUSWIDTH_4BIT 			&& (!sdio_card->cccr.lsc || sdio_card->cccr.ls4b)) {		sdio_set_bus_width(card, 2);	}		funcs = sdio_card->func_num;	/* enable function */	tmp = 0;	for(i = 1; i <= funcs; i++) {		tmp |= (1 << i); 	}	ret = sdio_io_enable(card, tmp);	if (ret)		return ret;			for(i = 1; i <= funcs; i++) {		ret = get_sdio_fbr_info(card, i);		if (ret)			return ret;	}	ret = get_sdio_ccis_info(card);	if (ret)		return ret;	for(i = 1; i <= funcs; i++) {		ret = get_sdio_fcis_info(card, i);		if (ret)			return ret;	}	/* enable interrupt */	tmp = 1;	for(i = 1; i <= funcs; i++) {		tmp |= (1 << i); 	}	ret = sdio_interrupt_enable(card, tmp);	if (ret)		return ret;			/* enable card capabilites */	for (i=1; i <= funcs; i++) {		sdio_csa_enable(card, i);	}	mss_set_sdio_int(card->slot->host, 1);	sdio_card->state = CARD_STATE_TRAN;	return MSS_ERROR_NONE;}static int sdio_read_write_entry(struct mss_card *card, int action, struct mss_rw_arg *arg, struct mss_rw_result *result){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_data *data = &sdio_card->data;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r5 r5;	struct sdio_response_r1 r1;	int ret;	u32 addr, blkmode, func, rw, rw_count, opcode, clock, cmdarg;	int retries = 4;		if (sdio_card->state == CARD_STATE_STBY) {		ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SELECT_CARD,				sdio_card->rca << 16, MSS_RESPONSE_R1B, 0);		if (ret)			return ret;		ret = sdio_unpack_r1(cmd, &r1, sdio_card);		if (ret)			return ret;	}	mss_set_clock(host, sdio_tran_speed(sdio_card->ccis.max_tran_speed)); 	func = arg->func;	if (func > sdio_card->func_num)		return MSS_ERROR_WRONG_ARG;			if (arg->block_len == 0 || arg->block_len == 1) {		blkmode = 0;	}	else {		if (!sdio_card->cccr.smb)			return MSS_ERROR_WRONG_ARG;		dbg("blkzs:%d, %d\n", arg->block_len, sdio_card->fbr[func].fn_blksz);		if (arg->block_len != sdio_card->fbr[func].fn_blksz) {			ret = sdio_set_block_size(card, arg->block_len, func);			if (ret)				return ret;		}		blkmode = 1;	}		rw = (action == MSS_READ_MEM) ? 0 : 1;	addr = arg->block;	opcode = (arg->opcode) ? 1 : 0;	rw_count = arg->nob;	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));	/* deal with request */	/* if only one byte, then use CMD52 to read*/	if (!blkmode && rw_count == 1) {		u8 val = (rw) ? arg->val : 0;		dbg("use CMD52 to transfer data. rw direction: %d", rw);		cmdarg = sdio_make_cmd52_arg(rw, func, opcode, addr, val);		ret = mss_send_simple_ll_req(host, llreq, cmd, IO_RW_DIRECT, 					cmdarg, MSS_RESPONSE_R5,				       	MSS_CMD_SDIO_EN);		if (!ret)			ret = sdio_unpack_r5(cmd, &r5, sdio_card);		if (!ret)			result->bytes_xfered = r5.data;		else if (ret && --retries) {			clock = host->ios.clock;			clock = clock >> 1;			if (clock < SDIO_CARD_CLOCK_SLOW && retries == 1) {				clock = SDIO_CARD_CLOCK_SLOW;				mss_set_clock(host, clock);				goto read_write_entry;			}			return ret;		}		dbg("r5.data:0x%x\n",r5.data);	}	else {		cmdarg= sdio_make_cmd53_arg(rw, func, blkmode, opcode, addr, 				rw_count);		MSS_INIT_CMD(cmd, IO_RW_EXTENDED, cmdarg, MSS_CMD_SDIO_EN, 				MSS_RESPONSE_R5);		MSS_INIT_DATA(data, rw_count, arg->block_len,  				((rw) ? MSS_DATA_WRITE : MSS_DATA_READ), 				arg->sg_len, arg->sg, 0);		llreq->cmd = cmd;		llreq->data = data;				ret = mss_send_ll_req(host, llreq);		if (!ret)			ret = sdio_unpack_r5(cmd, &r5, sdio_card);		if (ret) {			if (--retries) {				clock = host->ios.clock;				clock = clock >> 1;				if (clock < SDIO_CARD_CLOCK_SLOW 						&& retries == 1)					clock = SDIO_CARD_CLOCK_SLOW;				mss_set_clock(host, clock);				goto read_write_entry;			}			return ret;		}		}	return MSS_ERROR_NONE;}/***************************************************************************** * *   protocol driver interface functions * ****************************************************************************/static int sdio_prot_entry(struct mss_card *card, unsigned int action, void *arg, void *result){	int ret;		dbg("sdio_prot_entry\n");		if (action != MSS_RECOGNIZE_CARD && card->card_type != MSS_SDIO_CARD)		return MSS_ERROR_WRONG_CARD_TYPE;	switch (action) {		case MSS_RECOGNIZE_CARD:			ret = sdio_recognize_card(card);			break;		case MSS_INIT_CARD:			ret = sdio_card_init(card);			break;		case MSS_READ_MEM:		case MSS_WRITE_MEM:			if (!arg || !result)				return -EINVAL;			ret = sdio_read_write_entry(card, action, arg, result);			break;		case MSS_QUERY_CARD:			ret = MSS_ERROR_NONE;			break;		default:			ret = MSS_ERROR_ACTION_UNSUPPORTED;			break;	}		return ret;}static int sdio_prot_attach_card(struct mss_card *card){	struct sdio_card *sdio_card;		dbg("sdio_prot_attach_card\n");#define ALIGN32(x)	(((x) + 31) & (~31))	sdio_card = kzalloc(ALIGN32(sizeof(struct sdio_card)), GFP_KERNEL);	card->prot_card = sdio_card;	if (sdio_card) {		return 0;	}	return -ENOMEM;}static void sdio_prot_detach_card(struct mss_card *card){	kfree(card->prot_card);}static int sdio_prot_get_errno(struct mss_card *card){	struct sdio_card *sdio_card = card->prot_card;		return sdio_card->errno;}static struct mss_prot_driver sdio_protocol = {	.name			=	SDIO_PROTOCOL,	.prot_entry		=	sdio_prot_entry,	.attach_card		=	sdio_prot_attach_card,	.detach_card		=	sdio_prot_detach_card,	.get_errno		=	sdio_prot_get_errno,};/***************************************************************************** * *   module init and exit functions * ****************************************************************************/static int sdio_protocol_init(void){	register_mss_prot_driver(&sdio_protocol);	return 0;}static void sdio_protocol_exit(void){	unregister_mss_prot_driver(&sdio_protocol);}module_init(sdio_protocol_init);module_exit(sdio_protocol_exit);MODULE_AUTHOR("Bridge Wu");MODULE_LICENSE("Intel Private");MODULE_DESCRIPTION("SDIO protocol driver");

⌨️ 快捷键说明

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