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

📄 mmc.c

📁 dm320平台的LINUX mmc和sd卡驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif/* * Given the decoded CSD structure, decode the raw CID to our CID structure. */static void mmc_decode_cid(struct mmc_card *card){	u16 *resp =(unsigned short *) 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;                case 4: break;		default:			mmc_debug_msg("%s: card has unknown MMCA version %d\n",				mmc_hostname(card->host), card->csd.mmca_vsn);			mmc_card_set_bad(card);			break;		}	}}static void mmc_decode_csd(struct mmc_card *card){	struct mmc_csd *csd = &card->csd;	unsigned int e, m, csd_struct;	u16 *resp =(unsigned short *) card->raw_csd;	if (mmc_card_sd(card)) {		csd_struct = UNSTUFF_BITS(resp, 126, 2);		if (csd_struct != 0) {			mmc_debug_msg("%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);		mmc_debug_msg ("device_size : %d\n",m);		mmc_debug_msg ("device_size multiplier: %d\n",e);		//printk("\nCapacity : %d MB\n",(csd->capacity)/(2048));		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);		mmc_debug_msg ("blocklen : %d\n",(1 <<csd->read_blkbits));	} 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) {			mmc_debug_msg("%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;	u16 resp[4];#if 1 	BUG_ON(!mmc_card_sd(card));	resp[0] = card->raw_scr[0];	resp[1] = card->raw_scr[1];	resp[2] = card->raw_scr[2];	resp[3] = card->raw_scr[3];	scr_struct = (resp[0] >> 12) & 0x000F;	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 = (resp[0] >> 9) & 0x000F ; 	scr->bus_widths = resp[0] & 0x000F;#else	scr->bus_widths = SD_SCR_BUS_WIDTH_4;#endif}/* * 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)static struct mmc_card *mmc_find_card(struct mmc_host *host, u16 *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, u16 *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;		}	card->rca = rca;	*frca = rca;	return card;}/* * Tell attached cards to go to IDLE state */static void mmc_idle_cards(struct mmc_host *host){	struct mmc_command cmd;	host->ios.chip_select = MMC_CS_HIGH;	host->ops->set_ios(host, &host->ios);	//mmc_delay(1);		cmd.opcode = MMC_GO_IDLE_STATE | 0x0000;	cmd.arg = 0;	cmd.flags = MMCSD_RSPNONE;	mmc_wait_for_cmd(host, &cmd, 0);	//mmc_delay(1);	host->ios.chip_select = MMC_CS_DONTCARE;	host->ops->set_ios(host, &host->ios);	//mmc_delay(1);}/* * Apply power to the MMC stack. */static void mmc_power_up(struct mmc_host *host){	int bit = fls(host->ocr_avail) - 1;	host->ios.vdd = bit;	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;	host->ios.chip_select = MMC_CS_DONTCARE;	host->ios.power_mode = MMC_POWER_UP;	host->ios.bus_width = MMC_BUS_WIDTH_1;	host->ops->set_ios(host, &host->ios);	mmc_delay(1);	host->ios.clock = host->f_min;	host->ios.power_mode = MMC_POWER_ON;	host->ops->set_ios(host, &host->ios);	mmc_delay(2);}static void mmc_power_off(struct mmc_host *host){	host->ios.clock = 0;	host->ios.vdd = 0;	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;	host->ios.chip_select = MMC_CS_DONTCARE;	host->ios.power_mode = MMC_POWER_OFF;	host->ios.bus_width = MMC_BUS_WIDTH_1;	host->ops->set_ios(host, &host->ios);}static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr){	struct mmc_command cmd;	int err = 0;	cmd.opcode = MMC_SEND_OP_COND;	cmd.arg = ocr;	cmd.flags = MMCSD_RSP3;        err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);        	while (!((cmd.resp[6]|(cmd.resp[7] << 16)) & MMC_CARD_BUSY || ocr == 0)){		if (err != MMC_ERR_NONE)			break;		err =  mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);		mdelay(2);	}	if (rocr)		*rocr = cmd.resp[6]|(cmd.resp[7] << 16);	return err;}static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr){	struct mmc_command cmd;	int err = 0;	cmd.opcode = SD_APP_OP_COND;	cmd.arg = ocr;	cmd.flags = MMCSD_RSP3;#if 0		for (i = 200; i; i--) {		err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);		if (err != MMC_ERR_NONE)			break;		if ((cmd.resp[6]|(cmd.resp[7] << 16)) & MMC_CARD_BUSY || ocr == 0){			break;		}		err = MMC_ERR_TIMEOUT;				mdelay(2);	}#endif#if 1	err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);	while (!((cmd.resp[6]|(cmd.resp[7] << 16)) & MMC_CARD_BUSY || ocr == 0)){		if (err != MMC_ERR_NONE)			break;		err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);		mdelay(2);	}#endif	if (rocr)		*rocr = cmd.resp[6]|(cmd.resp[7] << 16);	return err;}/* * Discover cards by requesting their CID.  If this command * times out, it is not an error; there are no further cards * to be discovered.  Add new cards to the list. * * Create a mmc_card entry for each discovered card, assigning * it an RCA, and save the raw CID for decoding later. */static void mmc_discover_cards(struct mmc_host *host){	struct mmc_card *card;	unsigned int first_rca = 1, err;	while (1) 	{		struct mmc_command cmd;		cmd.opcode = MMC_ALL_SEND_CID;		cmd.arg = 0;		cmd.flags = MMCSD_RSP2;			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);		if (err == MMC_ERR_TIMEOUT) {			err = MMC_ERR_NONE;			break;		}		if (err != MMC_ERR_NONE) {			printk(KERN_ERR "%s: error requesting CID: %d\n",				mmc_hostname(host), err);			break;		}		mmc_debug_msg ("%s in %d\n",__FUNCTION__,__LINE__);		card = (struct mmc_card *)mmc_find_card(host, cmd.resp);		if (!card) {			mmc_debug_msg ("%s in %d\n",__FUNCTION__,__LINE__);			card = mmc_alloc_card(host, cmd.resp, &first_rca);			if (IS_ERR(card)) {				err = PTR_ERR(card);				break;			}			list_add(&card->node, &host->cards);		}		card->state &= ~MMC_STATE_DEAD;		if (host->mode == MMC_MODE_SD) {			mmc_card_set_sd(card);			cmd.opcode = SD_SEND_RELATIVE_ADDR;			cmd.arg = 0;			cmd.flags = MMCSD_RSP1;			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);			if (err != MMC_ERR_NONE)				mmc_card_set_dead(card);			else {				card->rca = cmd.resp[7];				if (!host->ops->get_ro) {					printk(KERN_WARNING "%s: host does not "						"support reading read-only "						"switch. assuming write-enable.\n",						mmc_hostname(host));				} else {					if (host->ops->get_ro(host)){						mmc_card_set_readonly(card);					}				}			}		} else {			cmd.opcode = MMC_SET_RELATIVE_ADDR;			cmd.arg = card->rca << 16;			cmd.flags = MMCSD_RSP6;			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);			if (err != MMC_ERR_NONE)				mmc_card_set_dead(card);		}	}}static void mmc_read_csds(struct mmc_host *host){	struct mmc_card *card;	mmc_debug_msg ("%s %d card->state : %d\n",__FUNCTION__,__LINE__,card->state);	list_for_each_entry(card, &host->cards, node) {		struct mmc_command cmd;		int err;		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))			continue;		cmd.opcode = MMC_SEND_CSD;		cmd.arg = card->rca << 16;		cmd.flags = MMCSD_RSP2;		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);		if (err != MMC_ERR_NONE) {			mmc_card_set_dead(card);			continue;		}		memcpy(card->raw_csd, cmd.resp, sizeof(card->raw_csd));		mmc_decode_csd(card);		mmc_decode_cid(card);	}}static void mmc_disable_pull_up(struct mmc_host *host){	int err;	struct mmc_card *card;	struct mmc_command cmd;	list_for_each_entry(card, &host->cards, node) {		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))			continue;		if (!mmc_card_sd(card))			continue;		err = mmc_select_card(host, card);		if (err != MMC_ERR_NONE) {			mmc_card_set_dead(card);			continue;		}					memset(&cmd, 0, sizeof(struct mmc_command));		cmd.opcode = MMC_APP_CMD;		cmd.arg = card->rca << 16;		cmd.flags = MMCSD_RSP1;		err = mmc_wait_for_cmd(host, &cmd, 0);		if ((err != MMC_ERR_NONE) || !(cmd.resp[6] & R1_APP_CMD)) {			mmc_card_set_dead(card);			continue;

⌨️ 快捷键说明

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