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

📄 mss_core.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 2 页
字号:
		card->prot_driver->detach_card(card);		card->prot_driver = NULL;			card->state &= ~MSS_CARD_INITED;	}	return 0;}/* * After knowing a card has been ejected from the slot, this function should  * be invoked. At last, unload card driver in card(done by card_driver->remove). */static int mss_eject_card(struct mss_card *card){	BUG_ON(!card);	__mss_eject_card(card);		card->slot->card = NULL;	card->slot = NULL;		return 0;}unsigned int mss_get_capacity(struct mss_card *card){	int ret; 	u32 cap;		mss_claim_host(card->slot->host, card);	ret = card->prot_driver->prot_entry(card, MSS_GET_CAPACITY, NULL, &cap);	mss_release_host(card->slot->host);	if (ret)		cap = 0;	return cap;}int mss_scan_slot(struct mss_slot *slot){	struct mss_card *card;	struct mss_host *host;	int ret = 0;	card = slot->card;	host = slot->host;    if (card)        printk(KERN_INFO "mss_scan_slot card_type is %d\n", card->card_type);	dbg("before scan:host:%d, slot:%d", host->id, slot->id);	down(&slot->scan);	/* slot has card in it before, and the card is resuming back */	if (card && (card->state & MSS_CARD_SUSPENDED)) { 		/* card was ejected when it is suspended */		if (host->ops->is_slot_empty 				&& host->ops->is_slot_empty(slot)) {			card->state |= MSS_CARD_REMOVING;			ret = MSS_ERROR_CARD_REMOVING;		}		else {			/* 			 * if host provides is_slot_empty, and it 			 * indicates that the card is in slot, then 			 * we try to init it.			 * else, we try to init it directly. Obvisouly			 * that if there is no card in the slot, the 			 * init will fail			 */			ret = mss_init_card(card);			if (ret == MSS_ERROR_MISMATCH_CARD)				card->state |= MSS_CARD_INVALID;		}	}	else if (card && (card->state & MSS_CARD_INVALID)) {		card->state &= ~MSS_CARD_INVALID;		ret = mss_eject_card(card);				if (!host->ops->is_slot_empty 			|| (host->ops->is_slot_empty && 				!host->ops->is_slot_empty(slot))) {			ret = mss_insert_card(slot);		}				}	/* slot has card in it before, and no suspend happens */	else if (card && (card->state & MSS_CARD_REGISTERED)) {		if (host->ops->is_slot_empty) {			/* card has been ejected */			if (host->ops->is_slot_empty(slot))				ret = mss_eject_card(card);		}		else {			/*			 * We try to send the status query command.			 * If card->state has set MSS_CARD_REGISRTEED,			 * it indicates that the card has finished 			 * identification process, and it will response			 * the SEND_STATUS command.			 */			if (mss_query_card(card))				/* Card has been ejected */				ret = mss_eject_card(card);		}	}	/* slot has card in it, but the card is not registered */	else if (card) {		/* This should never be happens, because when insert fail, 		 * we will delete the card 		 */		BUG();	}	/* slot has no card in it before */	else if (!card) {		if (host->ops->is_slot_empty) {			/* slot is not empty */			if (!host->ops->is_slot_empty(slot))				ret = mss_insert_card(slot);		}		else {			/* 			 * try to insert a card			 */			ret = mss_insert_card(slot);		}					}	else {		printk(KERN_ERR "Unexpected situation when scan host:%d"				", slot:%d, card state:0x%x\n", host->id, 				slot->id, card ? card->state : 0x0);		BUG();	}	up(&slot->scan);	dbg("after scan, host:%d, slot:%d", host->id, slot->id);	return ret;}void mss_scan_host(struct mss_host *host){	struct mss_slot *slot;	int i;		for (i = 0; i < host->slot_num; i++) { 		slot = &host->slots[i];		mss_scan_slot(slot);	}}void mss_force_card_remove(struct mss_card *card){	mss_eject_card(card);}static void mss_wait_done(struct mss_ll_request *llreq){	complete(llreq->done_data);}int mss_send_ll_req(struct mss_host *host, struct mss_ll_request *llreq){	DECLARE_COMPLETION(complete);	llreq->done = mss_wait_done;	llreq->done_data = &complete;	llreq->cmd->llreq = llreq;	llreq->cmd->error = MSS_ERROR_NONE;	if (llreq->data) 		llreq->cmd->data = llreq->data;	host->ops->request(host, llreq);	wait_for_completion(&complete);	dbg("CMD 0x%x, return error: %d", llreq->cmd->opcode, 			llreq->cmd->error);	return llreq->cmd->error;}int mss_send_simple_ll_req(struct mss_host *host, struct mss_ll_request *llreq, struct mss_cmd *cmd, u32 opcode, u32 arg, u32 rtype, u32 flags){	memset(llreq, 0x0, sizeof(struct mss_ll_request));	memset(cmd, 0x0, sizeof(struct mss_cmd));	cmd->opcode = opcode;	cmd->arg = arg;	cmd->rtype = rtype;	cmd->flags = flags;	llreq->cmd = cmd;	return mss_send_ll_req(host, llreq);}	/* * add controller into mss_host_list */int register_mss_host(struct mss_host *host){		list_add_tail(&host->node, &mss_host_list);	mss_power_off(host);	mss_power_up(host);	mss_idle_cards(host);	return 0;}/* *  delete controller from mss_controller_list */void unregister_mss_host(struct mss_host *host){	list_del(&host->node);}/***************************************************************************** * *   functions for protocol driver * ****************************************************************************//* * add protocol driver into mss_protocol_list */int register_mss_prot_driver(struct mss_prot_driver *drv){	struct list_head *item;	struct mss_host *host;	struct mss_slot *slot;	int i;	list_add(&drv->node, &mss_protocol_list); 	list_for_each(item, &mss_host_list) {		host = list_entry(item, struct mss_host, node);		for (i = 0; i < host->slot_num; i++) {			slot = &host->slots[i];			if (!slot->card) 				mss_scan_slot(slot);		}	}	return 0;}/* * delete protocol driver from mss_protocol_list */void unregister_mss_prot_driver(struct mss_prot_driver *drv){	struct mss_slot *slot;	struct list_head *item;	struct mss_host *host;	int i;	list_del(&drv->node);	list_for_each(item, &mss_host_list) {		host = list_entry(item, struct mss_host, node);		for (i = 0; i < host->slot_num; i++) {			slot = &host->slots[i];			if (slot->card && slot->card->prot_driver == drv)				mss_eject_card(slot->card);		}	}}/***************************************************************************** * *   interfaces for card driver * ****************************************************************************//* * register card driver onto MMC bus */int register_mss_driver (struct mss_driver *drv){	dbg("register mss driver :%s\n", drv->driver.name);	drv->driver.bus = &mmc_bus_type;	return driver_register(&drv->driver); /* will call card_driver->probe */}/* * unregister card driver from MMC bus */void unregister_mss_driver (struct mss_driver *drv){	driver_unregister(&drv->driver);}/* * enable SDIO interrupt, used by SDIO application driver */void mss_set_sdio_int(struct mss_host *host, int sdio_en){	host->ops->enable_sdio_int(host, sdio_en);}void mss_set_clock(struct mss_host *host, int clock){	struct mss_ios ios;	memcpy(&ios, &host->ios, sizeof(ios));	if (clock > host->f_max)		clock = host->f_max;	else if (clock < host->f_min)		clock = host->f_min;	ios.clock = clock;	host->ops->set_ios(host, &ios);}void mss_set_buswidth(struct mss_host *host, int buswidth){	struct mss_ios ios;	memcpy(&ios, &host->ios, sizeof(ios));	ios.bus_width = buswidth;	host->ops->set_ios(host, &ios);}void mss_set_busmode(struct mss_host *host, int busmode){	struct mss_ios ios;	memcpy(&ios, &host->ios, sizeof(ios));	ios.bus_mode = busmode;	host->ops->set_ios(host, &ios);}int mss_send_request(struct mss_request *req){	struct mss_host *host; 	struct mss_card *card;	int ret;	if (!req->card || !req->card->slot)		return -ENODEV;	card = req->card;	host = card->slot->host;	if (req->card->state & MSS_CARD_REMOVING)		return MSS_ERROR_CARD_REMOVING;	card->state |= MSS_CARD_HANDLEIO;	mss_claim_host(host, card);	ret = card->prot_driver->prot_entry(card, req->action, req->arg, 			req->result);	mss_release_host(host);	card->state &= ~MSS_CARD_HANDLEIO;	if (ret)		req->errno = card->prot_driver->get_errno(card);	dbg("Request for action :%d, protolcol :%s return error :%d", 			req->action, card->prot_driver->name, req->errno);		return ret;}struct mss_host * mss_alloc_host(unsigned int slot_num, unsigned int id, unsigned int private_size){	struct mss_host *host;	int i = 0, size;	size = sizeof(struct mss_host) + sizeof(struct mss_slot) * slot_num 		+ private_size;	host = (struct mss_host *)kzalloc(size, GFP_KERNEL);	if (!host)		return NULL;	host->id = id;	host->slot_num = slot_num;	while(i < slot_num) {		host->slots[i].id = i;		host->slots[i].host = host;		init_MUTEX(&host->slots[i].scan);		i++;	}	host->private = (void *)&host->slots[slot_num];	host->active_card = NULL;	init_waitqueue_head(&host->wq);	return host;}void mss_free_host(struct mss_host *host){	kfree(host);	}struct mss_host *mss_find_host(int id){	struct list_head *pos;	struct mss_host *host;	list_for_each(pos, &mss_host_list) {		host = list_entry(pos, struct mss_host, node);		if (host->id == id)			return host;	}	return NULL;}/***************************************************************************** * *   module init and exit functions * ****************************************************************************/static int mss_core_driver_init(void){	return bus_register(&mmc_bus_type);}static void mss_core_driver_exit(void){	bus_unregister(&mmc_bus_type);}EXPORT_SYMBOL(mss_scan_slot);EXPORT_SYMBOL(mss_scan_host);EXPORT_SYMBOL(mss_alloc_host);EXPORT_SYMBOL(mss_free_host);EXPORT_SYMBOL(mss_find_host);EXPORT_SYMBOL(mss_force_card_remove);EXPORT_SYMBOL(register_mss_host);EXPORT_SYMBOL(unregister_mss_host);EXPORT_SYMBOL(register_mss_driver);EXPORT_SYMBOL(unregister_mss_driver);EXPORT_SYMBOL(mss_send_request);EXPORT_SYMBOL(mss_get_capacity);EXPORT_SYMBOL(register_mss_prot_driver);EXPORT_SYMBOL(unregister_mss_prot_driver);EXPORT_SYMBOL(mss_send_ll_req);EXPORT_SYMBOL(mss_send_simple_ll_req);EXPORT_SYMBOL(mss_set_sdio_int);EXPORT_SYMBOL(mss_set_buswidth);EXPORT_SYMBOL(mss_set_clock);EXPORT_SYMBOL(mss_set_busmode);EXPORT_SYMBOL(mss_init_card);EXPORT_SYMBOL(mss_card_get);EXPORT_SYMBOL(mss_card_put);module_init(mss_core_driver_init);module_exit(mss_core_driver_exit);MODULE_AUTHOR("Chao Xie");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Core driver for MMC/SD/SDIO card");

⌨️ 快捷键说明

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