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

📄 mmc.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			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 */		case 4: /* MMC v4 */			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);		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);	} 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);		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);	}}/* * 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;		}	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;	mmc_set_ios(host);	mmc_delay(1);	cmd.opcode = MMC_GO_IDLE_STATE;	cmd.arg = 0;	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;	mmc_wait_for_cmd(host, &cmd, 0);	mmc_delay(1);	host->ios.chip_select = MMC_CS_DONTCARE;	mmc_set_ios(host);	mmc_delay(1);}/* * Apply power to the MMC stack.  This is a two-stage process. * First, we enable power to the card without the clock running. * We then wait a bit for the power to stabilise.  Finally, * enable the bus drivers and clock to the card. * * We must _NOT_ enable the clock prior to power stablising. * * If a host does all the power sequencing itself, ignore the * initial MMC_POWER_UP stage. */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;	mmc_set_ios(host);	mmc_delay(1);	host->ios.clock = host->f_min;	host->ios.power_mode = MMC_POWER_ON;	mmc_set_ios(host);	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;	mmc_set_ios(host);}static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr){	struct mmc_command cmd;	int i, err = 0;	cmd.opcode = MMC_SEND_OP_COND;	cmd.arg = ocr;	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;	for (i = 100; i; i--) {		err = mmc_wait_for_cmd(host, &cmd, 0);		if (err != MMC_ERR_NONE)			break;		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)			break;		err = MMC_ERR_TIMEOUT;		mmc_delay(10);	}	if (rocr)		*rocr = cmd.resp[0];	return err;}static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr){	struct mmc_command cmd;	int i, err = 0;	cmd.opcode = SD_APP_OP_COND;	cmd.arg = ocr;	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;	for (i = 100; i; i--) {		err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);		if (err != MMC_ERR_NONE)			break;		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)			break;		err = MMC_ERR_TIMEOUT;		mmc_delay(10);	}	if (rocr)		*rocr = cmd.resp[0];	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 = MMC_RSP_R2 | MMC_CMD_BCR;		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;		}		card = mmc_find_card(host, cmd.resp);		if (!card) {			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 = MMC_RSP_R6 | MMC_CMD_BCR;			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);			if (err != MMC_ERR_NONE)				mmc_card_set_dead(card);			else {				card->rca = cmd.resp[0] >> 16;				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 = MMC_RSP_R1 | MMC_CMD_AC;			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;	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 = MMC_RSP_R2 | MMC_CMD_AC;		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_process_ext_csds(struct mmc_host *host){	int err;	struct mmc_card *card;	struct mmc_request mrq;	struct mmc_command cmd;	struct mmc_data data;	struct scatterlist sg;	/*	 * As the ext_csd is so large and mostly unused, we don't store the	 * raw block in mmc_card.	 */	u8 *ext_csd;	ext_csd = kmalloc(512, GFP_KERNEL);	if (!ext_csd) {		printk("%s: could not allocate a buffer to receive the ext_csd."		       "mmc v4 cards will be treated as v3.\n",			mmc_hostname(host));		return;	}	list_for_each_entry(card, &host->cards, node) {		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))			continue;		if (mmc_card_sd(card))			continue;		if (card->csd.mmca_vsn < CSD_SPEC_VER_4)			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_SEND_EXT_CSD;		cmd.arg = 0;		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;		memset(&data, 0, sizeof(struct mmc_data));		mmc_set_data_timeout(&data, card, 0);		data.blksz = 512;		data.blocks = 1;		data.flags = MMC_DATA_READ;		data.sg = &sg;		data.sg_len = 1;		memset(&mrq, 0, sizeof(struct mmc_request));		mrq.cmd = &cmd;		mrq.data = &data;		sg_init_one(&sg, ext_csd, 512);		mmc_wait_for_req(host, &mrq);		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {			mmc_card_set_dead(card);			continue;		}		switch (ext_csd[EXT_CSD_CARD_TYPE]) {		case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:			card->ext_csd.hs_max_dtr = 52000000;			break;		case EXT_CSD_CARD_TYPE_26:			card->ext_csd.hs_max_dtr = 26000000;			break;		default:			/* MMC v4 spec says this cannot happen */			printk("%s: card is mmc v4 but doesn't support "			       "any high-speed modes.\n",				mmc_hostname(card->host));			mmc_card_set_bad(card);			continue;		}		/* Activate highspeed support. */		cmd.opcode = MMC_SWITCH;		cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |			  (EXT_CSD_HS_TIMING << 16) |			  (1 << 8) |			  EXT_CSD_CMD_SET_NORMAL;		cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);		if (err != MMC_ERR_NONE) {			printk("%s: failed to switch card to mmc v4 "			       "high-speed mode.\n",			       mmc_hostname(card->host));			continue;		}		mmc_card_set_highspeed(card);		/* Check for host support for wide-bus modes. */		if (!(host->caps & MMC_CAP_4_BIT_DATA)) {			continue;		}		/* Activate 4-bit support. */		cmd.opcode = MMC_SWITCH;		cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |			  (EXT_CSD_BUS_WIDTH << 16) |			  (EXT_CSD_BUS_WIDTH_4 << 8) |			  EXT_CSD_CMD_SET_NORMAL;		cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);		if (err != MMC_ERR_NONE) {			printk("%s: failed to switch card to "			       "mmc v4 4-bit bus mode.\n",			       mmc_hostname(card->host));			continue;		}		host->ios.bus_width = MMC_BUS_WIDTH_4;	}

⌨️ 快捷键说明

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