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

📄 cfi_flash.c

📁 最新版的u-boot,2008-10-18发布
💻 C
📖 第 1 页 / 共 4 页
字号:
{	info->cmd_reset = AMD_CMD_RESET;	cmdset_amd_read_jedec_ids(info);	flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);	return 0;}#ifdef CONFIG_FLASH_CFI_LEGACYstatic void flash_read_jedec_ids (flash_info_t * info){	info->manufacturer_id = 0;	info->device_id       = 0;	info->device_id2      = 0;	switch (info->vendor) {	case CFI_CMDSET_INTEL_PROG_REGIONS:	case CFI_CMDSET_INTEL_STANDARD:	case CFI_CMDSET_INTEL_EXTENDED:		cmdset_intel_read_jedec_ids(info);		break;	case CFI_CMDSET_AMD_STANDARD:	case CFI_CMDSET_AMD_EXTENDED:		cmdset_amd_read_jedec_ids(info);		break;	default:		break;	}}/*----------------------------------------------------------------------- * Call board code to request info about non-CFI flash. * board_flash_get_legacy needs to fill in at least: * info->portwidth, info->chipwidth and info->interface for Jedec probing. */static int flash_detect_legacy(ulong base, int banknum){	flash_info_t *info = &flash_info[banknum];	if (board_flash_get_legacy(base, banknum, info)) {		/* board code may have filled info completely. If not, we		   use JEDEC ID probing. */		if (!info->vendor) {			int modes[] = {				CFI_CMDSET_AMD_STANDARD,				CFI_CMDSET_INTEL_STANDARD			};			int i;			for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {				info->vendor = modes[i];				info->start[0] = base;				if (info->portwidth == FLASH_CFI_8BIT					&& info->interface == FLASH_CFI_X8X16) {					info->addr_unlock1 = 0x2AAA;					info->addr_unlock2 = 0x5555;				} else {					info->addr_unlock1 = 0x5555;					info->addr_unlock2 = 0x2AAA;				}				flash_read_jedec_ids(info);				debug("JEDEC PROBE: ID %x %x %x\n",						info->manufacturer_id,						info->device_id,						info->device_id2);				if (jedec_flash_match(info, base))					break;			}		}		switch(info->vendor) {		case CFI_CMDSET_INTEL_PROG_REGIONS:		case CFI_CMDSET_INTEL_STANDARD:		case CFI_CMDSET_INTEL_EXTENDED:			info->cmd_reset = FLASH_CMD_RESET;			break;		case CFI_CMDSET_AMD_STANDARD:		case CFI_CMDSET_AMD_EXTENDED:		case CFI_CMDSET_AMD_LEGACY:			info->cmd_reset = AMD_CMD_RESET;			break;		}		info->flash_id = FLASH_MAN_CFI;		return 1;	}	return 0; /* use CFI */}#elsestatic inline int flash_detect_legacy(ulong base, int banknum){	return 0; /* use CFI */}#endif/*----------------------------------------------------------------------- * detect if flash is compatible with the Common Flash Interface (CFI) * http://www.jedec.org/download/search/jesd68.pdf */static void flash_read_cfi (flash_info_t *info, void *buf,		unsigned int start, size_t len){	u8 *p = buf;	unsigned int i;	for (i = 0; i < len; i++)		p[i] = flash_read_uchar(info, start + i);}static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry){	int cfi_offset;	/* We do not yet know what kind of commandset to use, so we issue	   the reset command in both Intel and AMD variants, in the hope	   that AMD flash roms ignore the Intel command. */	flash_write_cmd (info, 0, 0, AMD_CMD_RESET);	flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);	for (cfi_offset=0;	     cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);	     cfi_offset++) {		flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset],				 FLASH_CMD_CFI);		if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')		    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')		    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {			flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,					sizeof(struct cfi_qry));			info->interface	= le16_to_cpu(qry->interface_desc);			info->cfi_offset = flash_offset_cfi[cfi_offset];			debug ("device interface is %d\n",			       info->interface);			debug ("found port %d chip %d ",			       info->portwidth, info->chipwidth);			debug ("port %d bits chip %d bits\n",			       info->portwidth << CFI_FLASH_SHIFT_WIDTH,			       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);			/* calculate command offsets as in the Linux driver */			info->addr_unlock1 = 0x555;			info->addr_unlock2 = 0x2aa;			/*			 * modify the unlock address if we are			 * in compatibility mode			 */			if (	/* x8/x16 in x8 mode */				((info->chipwidth == FLASH_CFI_BY8) &&					(info->interface == FLASH_CFI_X8X16)) ||				/* x16/x32 in x16 mode */				((info->chipwidth == FLASH_CFI_BY16) &&					(info->interface == FLASH_CFI_X16X32)))			{				info->addr_unlock1 = 0xaaa;				info->addr_unlock2 = 0x555;			}			info->name = "CFI conformant";			return 1;		}	}	return 0;}static int flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry){	debug ("flash detect cfi\n");	for (info->portwidth = CFG_FLASH_CFI_WIDTH;	     info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {		for (info->chipwidth = FLASH_CFI_BY8;		     info->chipwidth <= info->portwidth;		     info->chipwidth <<= 1)			if (__flash_detect_cfi(info, qry))				return 1;	}	debug ("not found\n");	return 0;}/* * Manufacturer-specific quirks. Add workarounds for geometry * reversal, etc. here. */static void flash_fixup_amd(flash_info_t *info, struct cfi_qry *qry){	/* check if flash geometry needs reversal */	if (qry->num_erase_regions > 1) {		/* reverse geometry if top boot part */		if (info->cfi_version < 0x3131) {			/* CFI < 1.1, try to guess from device id */			if ((info->device_id & 0x80) != 0)				cfi_reverse_geometry(qry);		} else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {			/* CFI >= 1.1, deduct from top/bottom flag */			/* note: ext_addr is valid since cfi_version > 0 */			cfi_reverse_geometry(qry);		}	}}static void flash_fixup_atmel(flash_info_t *info, struct cfi_qry *qry){	int reverse_geometry = 0;	/* Check the "top boot" bit in the PRI */	if (info->ext_addr && !(flash_read_uchar(info, info->ext_addr + 6) & 1))		reverse_geometry = 1;	/* AT49BV6416(T) list the erase regions in the wrong order.	 * However, the device ID is identical with the non-broken	 * AT49BV642D since u-boot only reads the low byte (they	 * differ in the high byte.) So leave out this fixup for now.	 */#if 0	if (info->device_id == 0xd6 || info->device_id == 0xd2)		reverse_geometry = !reverse_geometry;#endif	if (reverse_geometry)		cfi_reverse_geometry(qry);}/* * The following code cannot be run from FLASH! * */ulong flash_get_size (ulong base, int banknum){	flash_info_t *info = &flash_info[banknum];	int i, j;	flash_sect_t sect_cnt;	unsigned long sector;	unsigned long tmp;	int size_ratio;	uchar num_erase_regions;	int erase_region_size;	int erase_region_count;	struct cfi_qry qry;	memset(&qry, 0, sizeof(qry));	info->ext_addr = 0;	info->cfi_version = 0;#ifdef CFG_FLASH_PROTECTION	info->legacy_unlock = 0;#endif	info->start[0] = base;	if (flash_detect_cfi (info, &qry)) {		info->vendor = le16_to_cpu(qry.p_id);		info->ext_addr = le16_to_cpu(qry.p_adr);		num_erase_regions = qry.num_erase_regions;		if (info->ext_addr) {			info->cfi_version = (ushort) flash_read_uchar (info,						info->ext_addr + 3) << 8;			info->cfi_version |= (ushort) flash_read_uchar (info,						info->ext_addr + 4);		}#ifdef DEBUG		flash_printqry (&qry);#endif		switch (info->vendor) {		case CFI_CMDSET_INTEL_PROG_REGIONS:		case CFI_CMDSET_INTEL_STANDARD:		case CFI_CMDSET_INTEL_EXTENDED:			cmdset_intel_init(info, &qry);			break;		case CFI_CMDSET_AMD_STANDARD:		case CFI_CMDSET_AMD_EXTENDED:			cmdset_amd_init(info, &qry);			break;		default:			printf("CFI: Unknown command set 0x%x\n",					info->vendor);			/*			 * Unfortunately, this means we don't know how			 * to get the chip back to Read mode. Might			 * as well try an Intel-style reset...			 */			flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);			return 0;		}		/* Do manufacturer-specific fixups */		switch (info->manufacturer_id) {		case 0x0001:			flash_fixup_amd(info, &qry);			break;		case 0x001f:			flash_fixup_atmel(info, &qry);			break;		}		debug ("manufacturer is %d\n", info->vendor);		debug ("manufacturer id is 0x%x\n", info->manufacturer_id);		debug ("device id is 0x%x\n", info->device_id);		debug ("device id2 is 0x%x\n", info->device_id2);		debug ("cfi version is 0x%04x\n", info->cfi_version);		size_ratio = info->portwidth / info->chipwidth;		/* if the chip is x8/x16 reduce the ratio by half */		if ((info->interface == FLASH_CFI_X8X16)		    && (info->chipwidth == FLASH_CFI_BY8)) {			size_ratio >>= 1;		}		debug ("size_ratio %d port %d bits chip %d bits\n",		       size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);		debug ("found %d erase regions\n", num_erase_regions);		sect_cnt = 0;		sector = base;		for (i = 0; i < num_erase_regions; i++) {			if (i > NUM_ERASE_REGIONS) {				printf ("%d erase regions found, only %d used\n",					num_erase_regions, NUM_ERASE_REGIONS);				break;			}			tmp = le32_to_cpu(qry.erase_region_info[i]);			debug("erase region %u: 0x%08lx\n", i, tmp);			erase_region_count = (tmp & 0xffff) + 1;			tmp >>= 16;			erase_region_size =				(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;			debug ("erase_region_count = %d erase_region_size = %d\n",				erase_region_count, erase_region_size);			for (j = 0; j < erase_region_count; j++) {				if (sect_cnt >= CFG_MAX_FLASH_SECT) {					printf("ERROR: too many flash sectors\n");					break;				}				info->start[sect_cnt] = sector;				sector += (erase_region_size * size_ratio);				/*				 * Only read protection status from				 * supported devices (intel...)				 */				switch (info->vendor) {				case CFI_CMDSET_INTEL_PROG_REGIONS:				case CFI_CMDSET_INTEL_EXTENDED:				case CFI_CMDSET_INTEL_STANDARD:					info->protect[sect_cnt] =						flash_isset (info, sect_cnt,							     FLASH_OFFSET_PROTECT,							     FLASH_STATUS_PROTECT);					break;				default:					/* default: not protected */					info->protect[sect_cnt] = 0;				}				sect_cnt++;			}		}		info->sector_count = sect_cnt;		info->size = 1 << qry.dev_size;		/* multiply the size by the number of chips */		info->size *= size_ratio;		info->buffer_size = 1 << le16_to_cpu(qry.max_buf_write_size);		tmp = 1 << qry.block_erase_timeout_typ;		info->erase_blk_tout = tmp *			(1 << qry.block_erase_timeout_max);		tmp = (1 << qry.buf_write_timeout_typ) *			(1 << qry.buf_write_timeout_max);		/* round up when converting to ms */		info->buffer_write_tout = (tmp + 999) / 1000;		tmp = (1 << qry.word_write_timeout_typ) *			(1 << qry.word_write_timeout_max);		/* round up when converting to ms */		info->write_tout = (tmp + 999) / 1000;		info->flash_id = FLASH_MAN_CFI;		if ((info->interface == FLASH_CFI_X8X16) &&		    (info->chipwidth == FLASH_CFI_BY8)) {			/* XXX - Need to test on x8/x16 in parallel. */			info->portwidth >>= 1;		}		flash_write_cmd (info, 0, 0, info->cmd_reset);	}	return (info->size);}/*----------------------------------------------------------------------- */unsigned long flash_init (void){	unsigned long size = 0;	int i;#if defined(CFG_FLASH_AUTOPROTECT_LIST)	struct apl_s {		ulong start;		ulong size;	} apl[] = CFG_FLASH_AUTOPROTECT_LIST;#endif#ifdef CFG_FLASH_PROTECTION	char *s = getenv("unlock");#endif#define BANK_BASE(i)	(((unsigned long [CFI_MAX_FLASH_BANKS])CFG_FLASH_BANKS_LIST)[i])	/* Init: no FLASHes known */	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {		flash_info[i].flash_id = FLASH_UNKNOWN;		if (!flash_detect_legacy (BANK_BASE(i), i))			flash_get_size (BANK_BASE(i), i);		size += flash_info[i].size;		if (flash_info[i].flash_id == FLASH_UNKNOWN) {#ifndef CFG_FLASH_QUIET_TEST			printf ("## Unknown FLASH on Bank %d "				"- Size = 0x%08lx = %ld MB\n",				i+1, flash_info[i].size,				flash_info[i].size << 20);#endif /* CFG_FLASH_QUIET_TEST */		}#ifdef CFG_FLASH_PROTECTION		else if ((s != NULL) && (strcmp(s, "yes") == 0)) {			/*			 * Only the U-Boot image and it's environment			 * is protected, all other sectors are			 * unprotected (unlocked) if flash hardware			 * protection is used (CFG_FLASH_PROTECTION)			 * and the environment variable "unlock" is			 * set to "yes".			 */			if (flash_info[i].legacy_unlock) {				int k;				/*				 * Disable legacy_unlock temporarily,				 * since flash_real_protect would				 * relock all other sectors again				 * otherwise.				 */				flash_info[i].legacy_unlock = 0;				/*				 * Legacy unlocking (e.g. Intel J3) ->				 * unlock only one sector. This will				 * unlock all sectors.				 */				flash_real_protect (&flash_info[i], 0, 0);				flash_info[i].legacy_unlock = 1;				/*				 * Manually mark other sectors as				 * unlocked (unprotected)				 */				for (k = 1; k < flash_info[i].sector_count; k++)					flash_info[i].protect[k] = 0;			} else {				/*				 * No legancy unlocking -> unlock all sectors				 */				flash_protect (FLAG_PROTECT_CLEAR,					       flash_info[i].start[0],					       flash_info[i].start[0]					       + flash_info[i].size - 1,					       &flash_info[i]);			}		}#endif /* CFG_FLASH_PROTECTION */	}	/* Monitor protection ON by default */#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)	flash_protect (FLAG_PROTECT_SET,		       CFG_MONITOR_BASE,		       CFG_MONITOR_BASE + monitor_flash_len  - 1,		       flash_get_info(CFG_MONITOR_BASE));#endif	/* Environment protection ON by default */#ifdef CONFIG_ENV_IS_IN_FLASH	flash_protect (FLAG_PROTECT_SET,		       CONFIG_ENV_ADDR,		       CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,		       flash_get_info(CONFIG_ENV_ADDR));#endif	/* Redundant environment protection ON by default */#ifdef CONFIG_ENV_ADDR_REDUND	flash_protect (FLAG_PROTECT_SET,		       CONFIG_ENV_ADDR_REDUND,		       CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SIZE_REDUND - 1,		       flash_get_info(CONFIG_ENV_ADDR_REDUND));#endif#if defined(CFG_FLASH_AUTOPROTECT_LIST)	for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) {		debug("autoprotecting from %08x to %08x\n",		      apl[i].start, apl[i].start + apl[i].size - 1);		flash_protect (FLAG_PROTECT_SET,			       apl[i].start,			       apl[i].start + apl[i].size - 1,			       flash_get_info(apl[i].start));	}#endif	return (size);}

⌨️ 快捷键说明

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