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

📄 mss_core.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Core MMC driver functions * * Copyright (c) 2002 Hewlett-Packard Company *    * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: *   * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. *   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Many thanks to Alessandro Rubini and Jonathan Corbet! * * Author:  Andrew Christian *          6 May 2002  *(C) Copyright 2006 Marvell International Ltd.   * All Rights Reserved  *//* * mss_core.c - MMC/SD/SDIO Core driver * * Copyright (C) 2006 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/proc_fs.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/list.h>#include <linux/sysctl.h>#include <linux/suspend.h>#include <asm/uaccess.h>#include <asm/hardware.h>#include <asm/dma.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/sizes.h>#include <asm/types.h>#include <linux/mmc/mss_core.h>static LIST_HEAD(mss_protocol_list);static LIST_HEAD(mss_host_list);static inline void mss_delay(unsigned int ms){	if (ms < HZ / 1000) {		yield();		mdelay(ms);	} else {		msleep_interruptible(ms);	}}static void mss_power_up(struct mss_host *host){	struct mss_ios ios;		memcpy(&ios, &host->ios, sizeof(ios));	ios.vdd = host->vdd;	ios.chip_select = MSS_CS_NO_CARE;	ios.power_mode = MSS_POWER_UP;	host->ops->set_ios(host, &ios);	mss_delay(1);	ios.clock = host->f_min;	ios.power_mode = MSS_POWER_ON;	host->ops->set_ios(host, &ios);	mss_delay(2);}static void mss_power_off(struct mss_host *host){	struct mss_ios ios;		memcpy(&ios, &host->ios, sizeof(ios));	ios.clock = 0;	ios.chip_select = MSS_CS_NO_CARE;	ios.power_mode = MSS_POWER_OFF;	host->ops->set_ios(host, &ios);}static void mss_idle_cards(struct mss_host *host){	struct mss_ios ios;		memcpy(&ios, &host->ios, sizeof(ios));	ios.chip_select = MSS_CS_HIGH;	host->ops->set_ios(host, &ios);	mss_delay(1);	ios.chip_select = MSS_CS_NO_CARE;	host->ops->set_ios(host, &ios);	mss_delay(1);}/* * Only after card is initialized by protocol and be registed to mmc_bus, the * state is changed to MSS_CARD_REGISTERED. */static int mmc_bus_match(struct device *dev, struct device_driver *drv){	struct mss_card *card;	card = container_of(dev, struct mss_card, dev);	/* when card->state is MSS_CARD_REGISTERED,it is accepted by protocol */	if (card->prot_driver && (card->state & MSS_CARD_REGISTERED))		return 1;	return 0;		}static int mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size){	printk(KERN_INFO "*** HOT PLUG ***\n");	return 0;}static int mmc_bus_suspend(struct device * dev, pm_message_t state){	int ret = 0;	struct mss_card *card;		card = container_of(dev, struct mss_card, dev);	dbg("card name :%s, state:%d\n", card->dev.bus_id, card->state);		/*if (card->state & MSS_CARD_HANDLEIO)		return -EAGAIN;*/	if (card->state & MSS_CARD_SUSPENDED)		return 0;		dbg("dev driver:%p, suspend%p\n", dev->driver, 		(dev->driver)? dev->driver->suspend:NULL);	if (dev->driver && dev->driver->suspend) {		ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE);		if (ret == 0)			ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);		if (ret == 0)			ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);	}	if (ret == 0) {		/* mark MSS_CARD_SUSPEND here */		card->state |= MSS_CARD_SUSPENDED;	}	return ret;}/*  * card may be removed or replaced by another card from the mmc_bus when it is  * sleeping, and the slot may be inserted a card when it is sleeping. * The controller resume function need to take care about it. */static int mmc_bus_resume(struct device * dev){	int ret = 0;	struct mss_card *card;		card = container_of(dev, struct mss_card, dev);	dbg("card name :%s, state:%d\n", card->dev.bus_id, card->state);		/* it is new instered card or replaced card */	if (!(card->state & MSS_CARD_SUSPENDED))		return 0;		card->state &= ~MSS_CARD_SUSPENDED;	dbg("dev driver:%p, resume;%p\n", dev->driver, 		(dev->driver) ? dev->driver->resume:NULL);	if (dev->driver && dev->driver->resume) {		ret = dev->driver->resume(dev, RESUME_POWER_ON);		if (ret == 0)				ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);		if (ret == 0)			ret = dev->driver->resume(dev, RESUME_ENABLE);	}	return ret;}static struct bus_type mmc_bus_type = {	.name		=	"mmc_bus",	.match		=	mmc_bus_match,	.hotplug	=	mmc_bus_hotplug,	.suspend	=	mmc_bus_suspend,	.resume		=	mmc_bus_resume,};static void mss_card_device_release(struct device *dev){	struct mss_card *card = container_of(dev, struct mss_card, dev);	kfree(card);}static void mss_claim_host(struct mss_host *host, struct mss_card *card){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	spin_lock_irqsave(&host->lock, flags);	while (host->active_card != NULL) {		spin_unlock_irqrestore(&host->lock, flags);		set_current_state(TASK_UNINTERRUPTIBLE);		add_wait_queue(&host->wq, &wait);		schedule();		set_current_state(TASK_RUNNING);		remove_wait_queue(&host->wq, &wait);		spin_lock_irqsave(&host->lock, flags);	}	host->active_card = card;	spin_unlock_irqrestore(&host->lock, flags);}static void mss_release_host(struct mss_host* host){	unsigned long flags;	BUG_ON(host->active_card == NULL);	spin_lock_irqsave(&host->lock, flags);	host->active_card = NULL;	spin_unlock_irqrestore(&host->lock, flags);	wake_up(&host->wq);}int mss_card_get(struct mss_card *card){	if ((card->state & MSS_CARD_REMOVING) 			|| !(card->state & MSS_CARD_REGISTERED))		return -ENXIO;	if (!get_device(&card->dev))		return -ENXIO;	return 0;}void mss_card_put(struct mss_card *card){	put_device(&card->dev);}/* *  finish handling a request. */static void mss_finish_request(struct mss_request *req){	struct mss_driver *drv;	struct mss_card *card = req->card;	drv = container_of(card->dev.driver, struct mss_driver, driver);	if (drv && drv->request_done)		drv->request_done(req);}/* * Loop all the protocol in the mss_protocol_list, and find one protocol that * can successful recognize and init the card. */static int mss_attach_protocol(struct mss_card *card){	struct list_head *item;	struct mss_prot_driver *pdrv = NULL;	struct mss_host *host = card->slot->host;	int ret;	/* loop all the protocol, and find one that match the card */	list_for_each(item, &mss_protocol_list) {		pdrv = list_entry(item, struct mss_prot_driver, node);		ret = pdrv->attach_card(card);		if (ret)			continue;		mss_claim_host(host, card);		ret = pdrv->prot_entry(card, MSS_RECOGNIZE_CARD, NULL, NULL);		mss_release_host(host);		if (ret)			continue;		dbg("mss_attach_protocol: card type: %d \n",card->card_type);		switch (card->card_type) {			case MSS_MMC_CARD:			//case MSS_CE_ATA:			case MSS_SD_CARD:			case MSS_SDIO_CARD:			case MSS_COMBO_CARD:				goto identified;			/* 			 * The card can be recognized, but it deos not fit the 			 * controller.			 */			case MSS_UNCOMPATIBLE_CARD:				pdrv->detach_card(card);				return MSS_ERROR_NO_PROTOCOL;			/* The card can not be recognized by the protocl */			case MSS_UNKNOWN_CARD:				pdrv->detach_card(card);				break;				default:				pdrv->detach_card(card);				printk(KERN_WARNING "protocol driver :%s "						"return unknown value when"						" recognize the card\n", 						pdrv->name);				break;		}	}		return MSS_ERROR_NO_PROTOCOL;identified:	card->prot_driver = pdrv;	return 0;}/* Initialize card by the protocol */int mss_init_card(struct mss_card *card){	int ret;	struct mss_host *host = card->slot->host;		if (!card || !card->prot_driver)		return -EINVAL;	mss_claim_host(host, card);	ret = card->prot_driver->prot_entry(card, MSS_INIT_CARD, NULL, NULL);	mss_release_host(host);	return ret;}int mss_query_card(struct mss_card *card){		int ret;	struct mss_host *host = card->slot->host;		if (!card || !card->prot_driver)		return -EINVAL;	mss_claim_host(host, card);	ret = card->prot_driver->prot_entry(card, MSS_QUERY_CARD, NULL, NULL);	mss_release_host(host);	return ret;}static int __mss_insert_card(struct mss_card *card) {	int ret;	/* Step 1: Recognize the card */	ret = mss_attach_protocol(card);	if (ret)		return ret;		/* Step 2, initialize the card */	ret = mss_init_card(card);	if (ret) { 		goto detach_prot;	}	card->state |= MSS_CARD_INITED;	/* Step 3, register the card to mmc bus */	card->dev.release = mss_card_device_release;	card->dev.parent = card->slot->host->dev;	/* set bus_id and name */	snprintf(&card->dev.bus_id[0], sizeof(card->dev.bus_id), "mmc%d%d", 			card->slot->host->id, card->slot->id); 	card->dev.bus = &mmc_bus_type; 		card->state |= MSS_CARD_REGISTERED;	ret = device_register(&card->dev); /* will call mss_card_probe */		if (ret) {		ret = MSS_ERROR_REGISTER_CARD;		card->state &= ~MSS_CARD_REGISTERED;		goto detach_prot;	}	return MSS_ERROR_NONE;	detach_prot:	card->prot_driver->detach_card(card);	card->prot_driver = NULL;	return ret;}/* * After knowing a card has been inserted into the slot, this function should  * be invoked. At last, load card driver in card (done by card_driver->probe). */static int mss_insert_card(struct mss_slot *slot){	struct mss_card * card;	int ret;	BUG_ON(slot->card);	card = kzalloc(sizeof(struct mss_card), GFP_KERNEL);	if (!card)		return -ENOMEM;	card->slot = slot;	slot->card = card;	ret = __mss_insert_card(card);	if (ret) {		slot->card = NULL;		kfree(card);	}	return ret;}static int __mss_eject_card(struct mss_card *card){	card->state |= MSS_CARD_REMOVING;	if (card->state & MSS_CARD_REGISTERED) {		device_unregister(&(card->dev));		card->state &= ~MSS_CARD_REGISTERED;	}	if (card->prot_driver) {

⌨️ 快捷键说明

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