mmc.c

来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 663 行 · 第 1/2 页

C
663
字号
			return -1;		}		memcpy(mmc_buf + part_start, src, part_len);		if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) <		    0) {			return -1;		}		dst += part_len;		src += part_len;	}	debug	    ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",	     src, (ulong) dst, end, part_start, part_end, aligned_start,	     aligned_end);	for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) {		debug		    ("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",		     src, (ulong) dst, end, part_start, part_end, aligned_start,		     aligned_end);		if ((mmc_block_write(dst, (uchar *) src, mmc_block_size)) < 0) {			return -1;		}	}	debug	    ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",	     src, (ulong) dst, end, part_start, part_end, aligned_start,	     aligned_end);	if (part_end && dst < end) {		debug		    ("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",		     src, (ulong) dst, end, part_start, part_end, aligned_start,		     aligned_end);		if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) {			return -1;		}		memcpy(mmc_buf, src, part_end);		if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0) {			return -1;		}	}	return 0;}ulong/****************************************************/mmc_bread(int dev_num, ulong blknr, lbaint_t blkcnt, void *dst)/****************************************************/{	int mmc_block_size = MMC_BLOCK_SIZE;	ulong src = blknr * mmc_block_size + CFG_MMC_BASE;	mmc_read(src, (uchar *) dst, blkcnt * mmc_block_size);	return blkcnt;}#ifdef __GNUC__#define likely(x)       __builtin_expect(!!(x), 1)#define unlikely(x)     __builtin_expect(!!(x), 0)#else#define likely(x)	(x)#define unlikely(x)	(x)#endif#define UNSTUFF_BITS(resp,start,size)					\	({								\		const int __size = size;				\		const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1;	\		const int32_t __off = 3 - ((start) / 32);			\		const int32_t __shft = (start) & 31;			\		uint32_t __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(uint32_t * resp){	if (IF_TYPE_SD == mmc_dev.if_type) {		/*		 * SD doesn't currently have a version field so we will		 * have to assume we can parse this.		 */		sprintf((char *)mmc_dev.vendor,			"Man %02x OEM %c%c \"%c%c%c%c%c\" Date %02u/%04u",			UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp, 112, 8),			UNSTUFF_BITS(resp, 104, 8), UNSTUFF_BITS(resp, 96, 8),			UNSTUFF_BITS(resp, 88, 8), UNSTUFF_BITS(resp, 80, 8),			UNSTUFF_BITS(resp, 72, 8), UNSTUFF_BITS(resp, 64, 8),			UNSTUFF_BITS(resp, 8, 4), UNSTUFF_BITS(resp, 12,							       8) + 2000);		sprintf((char *)mmc_dev.revision, "%d.%d",			UNSTUFF_BITS(resp, 60, 4), UNSTUFF_BITS(resp, 56, 4));		sprintf((char *)mmc_dev.product, "%u",			UNSTUFF_BITS(resp, 24, 32));	} else {		/*		 * The selection of the format here is based upon published		 * specs from sandisk and from what people have reported.		 */		switch (spec_ver) {		case 0:	/* MMC v1.0 - v1.2 */		case 1:	/* MMC v1.4 */			sprintf((char *)mmc_dev.vendor,				"Man %02x%02x%02x \"%c%c%c%c%c%c%c\" Date %02u/%04u",				UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp,									 112,									 8),				UNSTUFF_BITS(resp, 104, 8), UNSTUFF_BITS(resp,									 96, 8),				UNSTUFF_BITS(resp, 88, 8), UNSTUFF_BITS(resp,									80, 8),				UNSTUFF_BITS(resp, 72, 8), UNSTUFF_BITS(resp,									64, 8),				UNSTUFF_BITS(resp, 56, 8), UNSTUFF_BITS(resp,									48, 8),				UNSTUFF_BITS(resp, 12, 4), UNSTUFF_BITS(resp, 8,									4) +				1997);			sprintf((char *)mmc_dev.revision, "%d.%d",				UNSTUFF_BITS(resp, 44, 4), UNSTUFF_BITS(resp,									40, 4));			sprintf((char *)mmc_dev.product, "%u",				UNSTUFF_BITS(resp, 16, 24));			break;		case 2:	/* MMC v2.0 - v2.2 */		case 3:	/* MMC v3.1 - v3.3 */		case 4:	/* MMC v4 */			sprintf((char *)mmc_dev.vendor,				"Man %02x OEM %04x \"%c%c%c%c%c%c\" Date %02u/%04u",				UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp,									 104,									 16),				UNSTUFF_BITS(resp, 96, 8), UNSTUFF_BITS(resp,									88, 8),				UNSTUFF_BITS(resp, 80, 8), UNSTUFF_BITS(resp,									72, 8),				UNSTUFF_BITS(resp, 64, 8), UNSTUFF_BITS(resp,									56, 8),				UNSTUFF_BITS(resp, 12, 4), UNSTUFF_BITS(resp, 8,									4) +				1997);			sprintf((char *)mmc_dev.product, "%u",				UNSTUFF_BITS(resp, 16, 32));			sprintf((char *)mmc_dev.revision, "N/A");			break;		default:			printf("MMC card has unknown MMCA version %d\n",			       spec_ver);			break;		}	}	printf("%s card.\nVendor: %s\nProduct: %s\nRevision: %s\n",	       (IF_TYPE_SD == mmc_dev.if_type) ? "SD" : "MMC", mmc_dev.vendor,	       mmc_dev.product, mmc_dev.revision);}/* * Given a 128-bit response, decode to our card CSD structure. */static void mmc_decode_csd(uint32_t * resp){	unsigned int mult, csd_struct;	if (IF_TYPE_SD == mmc_dev.if_type) {		csd_struct = UNSTUFF_BITS(resp, 126, 2);		if (csd_struct != 0) {			printf("SD: unrecognised CSD structure version %d\n",			       csd_struct);			return;		}	} 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) {			printf("MMC: unrecognised CSD structure version %d\n",			       csd_struct);			return;		}		spec_ver = UNSTUFF_BITS(resp, 122, 4);		mmc_dev.if_type = IF_TYPE_MMC;	}	mult = 1 << (UNSTUFF_BITS(resp, 47, 3) + 2);	mmc_dev.lba = (1 + UNSTUFF_BITS(resp, 62, 12)) * mult;	mmc_dev.blksz = 1 << UNSTUFF_BITS(resp, 80, 4);	/* FIXME: The following just makes assumes that's the partition type -- should really read it */	mmc_dev.part_type = PART_TYPE_DOS;	mmc_dev.dev = 0;	mmc_dev.lun = 0;	mmc_dev.type = DEV_TYPE_HARDDISK;	mmc_dev.removable = 0;	mmc_dev.block_read = mmc_bread;	printf("Detected: %lu blocks of %lu bytes (%luMB) ",		mmc_dev.lba,		mmc_dev.blksz,		mmc_dev.lba * mmc_dev.blksz / (1024 * 1024));}int/****************************************************/mmc_init(int verbose)/****************************************************/{	int retries, rc = -ENODEV;	uint32_t cid_resp[4];	uint32_t *resp;	uint16_t rca = 0;	/* Reset device interface type */	mmc_dev.if_type = IF_TYPE_UNKNOWN;#if defined (CONFIG_LUBBOCK) || (defined (CONFIG_GUMSTIX) && !defined(CONFIG_PXA27X))	set_GPIO_mode(GPIO6_MMCCLK_MD);	set_GPIO_mode(GPIO8_MMCCS0_MD);#endif	CKEN |= CKEN12_MMC;	/* enable MMC unit clock */	MMC_CLKRT = MMC_CLKRT_0_3125MHZ;	MMC_RESTO = MMC_RES_TO_MAX;	MMC_SPI = MMC_SPI_DISABLE;	/* reset */	mmc_cmd(MMC_CMD_GO_IDLE_STATE, 0, 0, MMC_CMDAT_INIT | MMC_CMDAT_R0);	udelay(200000);	retries = 3;	while (retries--) {		resp = mmc_cmd(MMC_CMD_APP_CMD, 0, 0, MMC_CMDAT_R1);		if (!(resp[0] & 0x00000020)) {	/* Card does not support APP_CMD */			debug("Card does not support APP_CMD\n");			break;		}		/* Select 3.2-3.3V and 3.3-3.4V */		resp = mmc_cmd(SD_CMD_APP_SEND_OP_COND, 0x0030, 0x0000,				MMC_CMDAT_R3 | (retries < 2 ? 0					: MMC_CMDAT_INIT));		if (resp[0] & 0x80000000) {			mmc_dev.if_type = IF_TYPE_SD;			debug("Detected SD card\n");			break;		}#ifdef CONFIG_PXA27X		udelay(10000);#else		udelay(200000);#endif	}	if (retries <= 0 || !(IF_TYPE_SD == mmc_dev.if_type)) {		debug("Failed to detect SD Card, trying MMC\n");		resp =		    mmc_cmd(MMC_CMD_SEND_OP_COND, 0x00ff, 0x8000, MMC_CMDAT_R3);		retries = 10;		while (retries-- && resp && !(resp[0] & 0x80000000)) {#ifdef CONFIG_PXA27X			udelay(10000);#else			udelay(200000);#endif			resp =			    mmc_cmd(MMC_CMD_SEND_OP_COND, 0x00ff, 0x8000,				    MMC_CMDAT_R3);		}	}	/* try to get card id */	resp =	    mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, 0, MMC_CMDAT_R2 | MMC_CMDAT_BUSY);	if (resp) {		memcpy(cid_resp, resp, sizeof(cid_resp));		/* MMC exists, get CSD too */		resp = mmc_cmd(MMC_CMD_SET_RELATIVE_ADDR, 0, 0, MMC_CMDAT_R1);		if (IF_TYPE_SD == mmc_dev.if_type)			rca = ((resp[0] & 0xffff0000) >> 16);		resp = mmc_cmd(MMC_CMD_SEND_CSD, rca, 0, MMC_CMDAT_R2);		if (resp) {			mmc_decode_csd(resp);			rc = 0;			mmc_ready = 1;		}		mmc_decode_cid(cid_resp);	}	MMC_CLKRT = 0;		/* 20 MHz */	resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca, 0, MMC_CMDAT_R1);#ifdef CONFIG_PXA27X	if (IF_TYPE_SD == mmc_dev.if_type) {		resp = mmc_cmd(MMC_CMD_APP_CMD, rca, 0, MMC_CMDAT_R1);		resp = mmc_cmd(SD_CMD_APP_SET_BUS_WIDTH, 0, 2, MMC_CMDAT_R1);		wide = MMC_CMDAT_SD_4DAT;	}#endif	fat_register_device(&mmc_dev, 1);	/* partitions start counting with 1 */	return rc;}int mmc_ident(block_dev_desc_t * dev){	return 0;}int mmc2info(ulong addr){	if (addr >= CFG_MMC_BASE	    && addr < CFG_MMC_BASE + (mmc_dev.lba * mmc_dev.blksz)) {		return 1;	}	return 0;}#endif /* CONFIG_MMC */

⌨️ 快捷键说明

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