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

📄 mmc.c.svn-base

📁 linux2.6.18下支持sd2.0的驱动程序源码,支持最大32G的SD卡
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/mmc/mmc.c * *  Copyright (C) 2003-2004 Russell King, All Rights Reserved. *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. *  SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/completion.h>#include <linux/device.h>#include <linux/delay.h>#include <linux/pagemap.h>#include <linux/err.h>#include <asm/scatterlist.h>#include <linux/scatterlist.h>#include <linux/mmc/card.h>#include <linux/mmc/host.h>#include <linux/mmc/protocol.h>#include "mmc.h"#ifdef CONFIG_MMC_DEBUG#define DBG(x...)	printk(KERN_DEBUG x)#else#define DBG(x...)	do { } while (0)#endif#define CMD_RETRIES	3/* * OCR Bit positions to 10s of Vdd mV. */static const unsigned short mmc_ocr_bit_to_vdd[] = {	150,	155,	160,	165,	170,	180,	190,	200,	210,	220,	230,	240,	250,	260,	270,	280,	290,	300,	310,	320,	330,	340,	350,	360};static const unsigned int tran_exp[] = {	10000,		100000,		1000000,	10000000,	0,		0,		0,		0};static const unsigned char tran_mant[] = {	0,	10,	12,	13,	15,	20,	25,	30,	35,	40,	45,	50,	55,	60,	70,	80,};static const unsigned int tacc_exp[] = {	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,};static const unsigned int tacc_mant[] = {	0,	10,	12,	13,	15,	20,	25,	30,	35,	40,	45,	50,	55,	60,	70,	80,};/** *	mmc_request_done - finish processing an MMC command *	@host: MMC host which completed command *	@mrq: MMC request which completed * *	MMC drivers should call this function when they have completed *	their processing of a command.  This should be called before the *	data part of the command has completed. */void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq){	struct mmc_command *cmd = mrq->cmd;	int err = mrq->cmd->error;	DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode,	    err, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);	if (err && cmd->retries) {		cmd->retries--;		cmd->error = 0;		host->ops->request(host, mrq);	} else if (mrq->done) {		mrq->done(mrq);	}}EXPORT_SYMBOL(mmc_request_done);/** *	mmc_start_request - start a command on a host *	@host: MMC host to start command on *	@mrq: MMC request to start * *	Queue a command on the specified host.  We expect the *	caller to be holding the host lock with interrupts disabled. */voidmmc_start_request(struct mmc_host *host, struct mmc_request *mrq){	DBG("MMC: starting cmd 0x%02x arg 0x%08x flags %08x\n",	    mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);	WARN_ON(host->card_busy == NULL);	mrq->cmd->error = 0;	mrq->cmd->mrq = mrq;	if (mrq->data) {		mrq->cmd->data = mrq->data;		mrq->data->error = 0;		mrq->data->mrq = mrq;		if (mrq->stop) {			mrq->data->stop = mrq->stop;			mrq->stop->error = 0;			mrq->stop->mrq = mrq;		}	}	host->ops->request(host, mrq);}EXPORT_SYMBOL(mmc_start_request);static void mmc_wait_done(struct mmc_request *mrq){	complete(mrq->done_data);}int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq){	DECLARE_COMPLETION(complete);	mrq->done_data = &complete;	mrq->done = mmc_wait_done;	mmc_start_request(host, mrq);	wait_for_completion(&complete);	return 0;}EXPORT_SYMBOL(mmc_wait_for_req);/** *	mmc_wait_for_cmd - start a command and wait for completion *	@host: MMC host to start command *	@cmd: MMC command to start *	@retries: maximum number of retries * *	Start a new MMC command for a host, and wait for the command *	to complete.  Return any error that occurred while the command *	was executing.  Do not attempt to parse the response. */int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries){	struct mmc_request mrq;	BUG_ON(host->card_busy == NULL);	memset(&mrq, 0, sizeof(struct mmc_request));	memset(cmd->resp, 0, sizeof(cmd->resp));	cmd->retries = retries;	mrq.cmd = cmd;	cmd->data = NULL;	mmc_wait_for_req(host, &mrq);	return cmd->error;}EXPORT_SYMBOL(mmc_wait_for_cmd);/** *	mmc_wait_for_app_cmd - start an application command and wait for 			       completion *	@host: MMC host to start command *	@rca: RCA to send MMC_APP_CMD to *	@cmd: MMC command to start *	@retries: maximum number of retries * *	Sends a MMC_APP_CMD, checks the card response, sends the command *	in the parameter and waits for it to complete. Return any error *	that occurred while the command was executing.  Do not attempt to *	parse the response. */int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,	struct mmc_command *cmd, int retries){	struct mmc_request mrq;	struct mmc_command appcmd;	int i, err;	BUG_ON(host->card_busy == NULL);	BUG_ON(retries < 0);	err = MMC_ERR_INVALID;	/*	 * We have to resend MMC_APP_CMD for each attempt so	 * we cannot use the retries field in mmc_command.	 */	for (i = 0;i <= retries;i++) {		memset(&mrq, 0, sizeof(struct mmc_request));		appcmd.opcode = MMC_APP_CMD;		appcmd.arg = rca << 16;		appcmd.flags = MMC_RSP_R1;		appcmd.retries = 0;		memset(appcmd.resp, 0, sizeof(appcmd.resp));		appcmd.data = NULL;		mrq.cmd = &appcmd;		appcmd.data = NULL;		mmc_wait_for_req(host, &mrq);		if (appcmd.error) {			err = appcmd.error;			continue;		}		/* Check that card supported application commands */		if (!(appcmd.resp[0] & R1_APP_CMD))			return MMC_ERR_FAILED;		memset(&mrq, 0, sizeof(struct mmc_request));		memset(cmd->resp, 0, sizeof(cmd->resp));		cmd->retries = 0;		mrq.cmd = cmd;		cmd->data = NULL;		mmc_wait_for_req(host, &mrq);		err = cmd->error;		if (cmd->error == MMC_ERR_NONE)			break;	}	return err;}EXPORT_SYMBOL(mmc_wait_for_app_cmd);static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);/** *	__mmc_claim_host - exclusively claim a host *	@host: mmc host to claim *	@card: mmc card to claim host for * *	Claim a host for a set of operations.  If a valid card *	is passed and this wasn't the last card selected, select *	the card before returning. * *	Note: you should use mmc_card_claim_host or mmc_claim_host. */int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	int err = 0;	add_wait_queue(&host->wq, &wait);	spin_lock_irqsave(&host->lock, flags);	while (1) {		set_current_state(TASK_UNINTERRUPTIBLE);		if (host->card_busy == NULL)			break;		spin_unlock_irqrestore(&host->lock, flags);		schedule();		spin_lock_irqsave(&host->lock, flags);	}	set_current_state(TASK_RUNNING);	host->card_busy = card;	spin_unlock_irqrestore(&host->lock, flags);	remove_wait_queue(&host->wq, &wait);	if (card != (void *)-1) {		err = mmc_select_card(host, card);		if (err != MMC_ERR_NONE)			return err;	}	return err;}EXPORT_SYMBOL(__mmc_claim_host);/** *	mmc_release_host - release a host *	@host: mmc host to release * *	Release a MMC host, allowing others to claim the host *	for their operations. */void mmc_release_host(struct mmc_host *host){	unsigned long flags;	BUG_ON(host->card_busy == NULL);	spin_lock_irqsave(&host->lock, flags);	host->card_busy = NULL;	spin_unlock_irqrestore(&host->lock, flags);	wake_up(&host->wq);}EXPORT_SYMBOL(mmc_release_host);static int mmc_select_card(struct mmc_host *host, struct mmc_card *card){	int err;	struct mmc_command cmd;	BUG_ON(host->card_busy == NULL);	if (host->card_selected == card)		return MMC_ERR_NONE;	host->card_selected = card;	cmd.opcode = MMC_SELECT_CARD;	cmd.arg = card->rca << 16;	cmd.flags = MMC_RSP_R1;	err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);	if (err != MMC_ERR_NONE)		return err;	/*	 * Default bus width is 1 bit.	 */	host->ios.bus_width = MMC_BUS_WIDTH_1;	/*	 * We can only change the bus width of the selected	 * card so therefore we have to put the handling	 * here.	 */	if (host->caps & MMC_CAP_4_BIT_DATA) {		/*		 * The card is in 1 bit mode by default so		 * we only need to change if it supports the		 * wider version.		 */		if (mmc_card_sd(card) &&			(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {			struct mmc_command cmd;			cmd.opcode = SD_APP_SET_BUS_WIDTH;			cmd.arg = SD_BUS_WIDTH_4;			cmd.flags = MMC_RSP_R1;			err = mmc_wait_for_app_cmd(host, card->rca, &cmd,				CMD_RETRIES);			if (err != MMC_ERR_NONE)				return err;			host->ios.bus_width = MMC_BUS_WIDTH_4;					}	}	host->ops->set_ios(host, &host->ios);	return MMC_ERR_NONE;}/* * Ensure that no card is selected. */static void mmc_deselect_cards(struct mmc_host *host){	struct mmc_command cmd;	if (host->card_selected) {		host->card_selected = NULL;		cmd.opcode = MMC_SELECT_CARD;		cmd.arg = 0;		cmd.flags = MMC_RSP_NONE;		mmc_wait_for_cmd(host, &cmd, 0);	}}static inline void mmc_delay(unsigned int ms){	if (ms < HZ / 1000) {		yield();		mdelay(ms);	} else {		msleep_interruptible (ms);	}}/* * Mask off any voltages we don't support and select * the lowest voltage */static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr){	int bit;	ocr &= host->ocr_avail;	bit = ffs(ocr);	if (bit) {		bit -= 1;		ocr = 3 << bit;		host->ios.vdd = bit;		host->ops->set_ios(host, &host->ios);	} else {		ocr = 0;	}	return ocr;}#define UNSTUFF_BITS(resp,start,size)					\	({								\		const int __size = size;				\		const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1;	\		const int __off = 3 - ((start) / 32);			\		const int __shft = (start) & 31;			\		u32 __res;						\									\		__res = resp[__off] >> __shft;				\		if (__size + __shft > 32)				\			__res |= resp[__off-1] << ((32 - __shft) % 32);	\		__res & __mask;						\	})/* * Given the decoded CSD structure, decode the raw CID to our CID structure. */static void mmc_decode_cid(struct mmc_card *card){	u32 *resp = card->raw_cid;	memset(&card->cid, 0, sizeof(struct mmc_cid));	if (mmc_card_sd(card)) {		/*		 * SD doesn't currently have a version field so we will		 * have to assume we can parse this.		 */		card->cid.manfid		= UNSTUFF_BITS(resp, 120, 8);		card->cid.oemid			= UNSTUFF_BITS(resp, 104, 16);		card->cid.prod_name[0]		= UNSTUFF_BITS(resp, 96, 8);		card->cid.prod_name[1]		= UNSTUFF_BITS(resp, 88, 8);		card->cid.prod_name[2]		= UNSTUFF_BITS(resp, 80, 8);		card->cid.prod_name[3]		= UNSTUFF_BITS(resp, 72, 8);		card->cid.prod_name[4]		= UNSTUFF_BITS(resp, 64, 8);		card->cid.hwrev			= UNSTUFF_BITS(resp, 60, 4);		card->cid.fwrev			= UNSTUFF_BITS(resp, 56, 4);		card->cid.serial		= UNSTUFF_BITS(resp, 24, 32);		card->cid.year			= UNSTUFF_BITS(resp, 12, 8);		card->cid.month			= UNSTUFF_BITS(resp, 8, 4);		card->cid.year += 2000; /* SD cards year offset */	} else {		/*		 * The selection of the format here is based upon published		 * specs from sandisk and from what people have reported.		 */		switch (card->csd.mmca_vsn) {		case 0: /* MMC v1.0 - v1.2 */		case 1: /* MMC v1.4 */			card->cid.manfid	= UNSTUFF_BITS(resp, 104, 24);			card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);			card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);			card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);			card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);			card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);			card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);			card->cid.prod_name[6]	= UNSTUFF_BITS(resp, 48, 8);			card->cid.hwrev		= UNSTUFF_BITS(resp, 44, 4);			card->cid.fwrev		= UNSTUFF_BITS(resp, 40, 4);			card->cid.serial	= UNSTUFF_BITS(resp, 16, 24);			card->cid.month		= UNSTUFF_BITS(resp, 12, 4);			card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;			break;		case 2: /* MMC v2.0 - v2.2 */		case 3: /* MMC v3.1 - v3.3 */			card->cid.manfid	= UNSTUFF_BITS(resp, 120, 8);			card->cid.oemid		= UNSTUFF_BITS(resp, 104, 16);			card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);			card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);			card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);			card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);			card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);			card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);			card->cid.serial	= UNSTUFF_BITS(resp, 16, 32);			card->cid.month		= UNSTUFF_BITS(resp, 12, 4);			card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;			break;		default:			printk("%s: card has unknown MMCA version %d\n",				mmc_hostname(card->host), card->csd.mmca_vsn);			mmc_card_set_bad(card);			break;		}	}	}/* * Given a 128-bit response, decode to our card CSD structure. */static void mmc_decode_csd(struct mmc_card *card){	struct mmc_csd *csd = &card->csd;	unsigned int e, m, csd_struct;	u32 *resp = card->raw_csd;	if (mmc_card_sd(card)) {		csd_struct = UNSTUFF_BITS(resp, 126, 2);		if (csd_struct != 0) {			printk("%s: unrecognised CSD structure version %d\n",				mmc_hostname(card->host), csd_struct);			mmc_card_set_bad(card);			return;		}		m = UNSTUFF_BITS(resp, 115, 4);		e = UNSTUFF_BITS(resp, 112, 3);		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;				m = UNSTUFF_BITS(resp, 99, 4);		e = UNSTUFF_BITS(resp, 96, 3);		csd->max_dtr	  = tran_exp[e] * tran_mant[m];		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);		e = UNSTUFF_BITS(resp, 47, 3);		m = UNSTUFF_BITS(resp, 62, 12);		csd->capacity	  = (1 + m) << (e + 2);		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);	} else {		/*		 * We only understand CSD structure v1.1 and v1.2.		 * v1.2 has extra information in bits 15, 11 and 10.		 */		csd_struct = UNSTUFF_BITS(resp, 126, 2);		if (csd_struct != 1 && csd_struct != 2) {			printk("%s: unrecognised CSD structure version %d\n",				mmc_hostname(card->host), csd_struct);			mmc_card_set_bad(card);			return;		}		csd->mmca_vsn	 = UNSTUFF_BITS(resp, 122, 4);		m = UNSTUFF_BITS(resp, 115, 4);		e = UNSTUFF_BITS(resp, 112, 3);		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;		m = UNSTUFF_BITS(resp, 99, 4);		e = UNSTUFF_BITS(resp, 96, 3);		csd->max_dtr	  = tran_exp[e] * tran_mant[m];		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);		e = UNSTUFF_BITS(resp, 47, 3);		m = UNSTUFF_BITS(resp, 62, 12);		csd->capacity	  = (1 + m) << (e + 2);		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);	}}/* * Given a 64-bit response, decode to our card SCR structure. */static void mmc_decode_scr(struct mmc_card *card){	struct sd_scr *scr = &card->scr;	unsigned int scr_struct;	u32 resp[4];	BUG_ON(!mmc_card_sd(card));	resp[3] = card->raw_scr[1];	resp[2] = card->raw_scr[0];	scr_struct = UNSTUFF_BITS(resp, 60, 4);	if (scr_struct != 0) {		printk("%s: unrecognised SCR structure version %d\n",			mmc_hostname(card->host), scr_struct);		mmc_card_set_bad(card);		return;	}	scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);	scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);}/* * Locate a MMC card on this MMC host given a raw CID. */static struct mmc_card *mmc_find_card(struct mmc_host *host, u32 *raw_cid){	struct mmc_card *card;	list_for_each_entry(card, &host->cards, node) {		if (memcmp(card->raw_cid, raw_cid, sizeof(card->raw_cid)) == 0)			return card;	}	return NULL;}/* * Allocate a new MMC card, and assign a unique RCA. */static struct mmc_card *mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca){	struct mmc_card *card, *c;	unsigned int rca = *frca;	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);	if (!card)		return ERR_PTR(-ENOMEM);	mmc_init_card(card, host);	memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid)); again:	list_for_each_entry(c, &host->cards, node)		if (c->rca == rca) {			rca++;			goto again;		}

⌨️ 快捷键说明

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