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

📄 cfi_flash.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 3 页
字号:
			} else				putc ('.');		}	}	puts (" done\n");	return rcode;}/*----------------------------------------------------------------------- */void flash_print_info (flash_info_t * info){	int i;	if (info->flash_id != FLASH_MAN_CFI) {		puts ("missing or unknown FLASH type\n");		return;	}	printf ("CFI conformant FLASH (%d x %d)",		(info->portwidth << 3), (info->chipwidth << 3));	printf ("  Size: %ld MB in %d Sectors\n",		info->size >> 20, info->sector_count);	printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n",		info->erase_blk_tout,		info->write_tout,		info->buffer_write_tout,		info->buffer_size);	puts ("  Sector Start Addresses:");	for (i = 0; i < info->sector_count; ++i) {#ifdef CFG_FLASH_EMPTY_INFO		int k;		int size;		int erased;		volatile unsigned long *flash;		/*		 * Check if whole sector is erased		 */		if (i != (info->sector_count - 1))			size = info->start[i + 1] - info->start[i];		else			size = info->start[0] + info->size - info->start[i];		erased = 1;		flash = (volatile unsigned long *) info->start[i];		size = size >> 2;	/* divide by 4 for longword access */		for (k = 0; k < size; k++) {			if (*flash++ != 0xffffffff) {				erased = 0;				break;			}		}		if ((i % 5) == 0)			printf ("\n");		/* print empty and read-only info */		printf (" %08lX%s%s",			info->start[i],			erased ? " E" : "  ",			info->protect[i] ? "RO " : "   ");#else		if ((i % 5) == 0)			printf ("\n   ");		printf (" %08lX%s",			info->start[i], info->protect[i] ? " (RO)  " : "     ");#endif	}	putc ('\n');	return;}/*----------------------------------------------------------------------- * Copy memory to flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt){	ulong wp;	ulong cp;	int aln;	cfiword_t cword;	int i, rc;#ifdef CFG_FLASH_USE_BUFFER_WRITE	int buffered_size;#endif	/* get lower aligned address */	/* get lower aligned address */	wp = (addr & ~(info->portwidth - 1));	/* handle unaligned start */	if ((aln = addr - wp) != 0) {		cword.l = 0;		cp = wp;		for (i = 0; i < aln; ++i, ++cp)			flash_add_byte (info, &cword, (*(uchar *) cp));		for (; (i < info->portwidth) && (cnt > 0); i++) {			flash_add_byte (info, &cword, *src++);			cnt--;			cp++;		}		for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)			flash_add_byte (info, &cword, (*(uchar *) cp));		if ((rc = flash_write_cfiword (info, wp, cword)) != 0)			return rc;		wp = cp;	}	/* handle the aligned part */#ifdef CFG_FLASH_USE_BUFFER_WRITE	buffered_size = (info->portwidth / info->chipwidth);	buffered_size *= info->buffer_size;	while (cnt >= info->portwidth) {		i = buffered_size > cnt ? cnt : buffered_size;		if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)			return rc;		i -= (i % info->portwidth);		wp += i;		src += i;		cnt -= i;	}#else	while (cnt >= info->portwidth) {		cword.l = 0;		for (i = 0; i < info->portwidth; i++) {			flash_add_byte (info, &cword, *src++);		}		if ((rc = flash_write_cfiword (info, wp, cword)) != 0)			return rc;		wp += info->portwidth;		cnt -= info->portwidth;	}#endif /* CFG_FLASH_USE_BUFFER_WRITE */	if (cnt == 0) {		return (0);	}	/*	 * handle unaligned tail bytes	 */	cword.l = 0;	for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {		flash_add_byte (info, &cword, *src++);		--cnt;	}	for (; i < info->portwidth; ++i, ++cp) {		flash_add_byte (info, &cword, (*(uchar *) cp));	}	return flash_write_cfiword (info, wp, cword);}/*----------------------------------------------------------------------- */#ifdef CFG_FLASH_PROTECTIONint flash_real_protect (flash_info_t * info, long sector, int prot){	int retcode = 0;	flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);	flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);	if (prot)		flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);	else		flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);	if ((retcode =	     flash_full_status_check (info, sector, info->erase_blk_tout,				      prot ? "protect" : "unprotect")) == 0) {		info->protect[sector] = prot;		/* Intel's unprotect unprotects all locking */		if (prot == 0) {			flash_sect_t i;			for (i = 0; i < info->sector_count; i++) {				if (info->protect[i])					flash_real_protect (info, i, 1);			}		}	}	return retcode;}/*----------------------------------------------------------------------- * flash_read_user_serial - read the OneTimeProgramming cells */void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,			     int len){	uchar *src;	uchar *dst;	dst = buffer;	src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);	flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);	memcpy (dst, src + offset, len);	flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);}/* * flash_read_factory_serial - read the device Id from the protection area */void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,				int len){	uchar *src;	src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);	flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);	memcpy (buffer, src + offset, len);	flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);}#endif /* CFG_FLASH_PROTECTION *//* * flash_is_busy - check to see if the flash is busy * This routine checks the status of the chip and returns true if the chip is busy */static int flash_is_busy (flash_info_t * info, flash_sect_t sect){	int retval;	switch (info->vendor) {	case CFI_CMDSET_INTEL_STANDARD:	case CFI_CMDSET_INTEL_EXTENDED:		retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);		break;	case CFI_CMDSET_AMD_STANDARD:	case CFI_CMDSET_AMD_EXTENDED:		retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);		break;	default:		retval = 0;	}	debug ("flash_is_busy: %d\n", retval);	return retval;}/*----------------------------------------------------------------------- *  wait for XSR.7 to be set. Time out with an error if it does not. *  This routine does not set the flash to read-array mode. */static int flash_status_check (flash_info_t * info, flash_sect_t sector,			       ulong tout, char *prompt){	ulong start;	/* Wait for command completion */	start = get_timer (0);	while (flash_is_busy (info, sector)) {		if (get_timer (start) > info->erase_blk_tout * CFG_HZ) {			printf ("Flash %s timeout at address %lx data %lx\n",				prompt, info->start[sector],				flash_read_long (info, sector, 0));			flash_write_cmd (info, sector, 0, info->cmd_reset);			return ERR_TIMOUT;		}	}	return ERR_OK;}/*----------------------------------------------------------------------- * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check. * This routine sets the flash to read-array mode. */static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,				    ulong tout, char *prompt){	int retcode;	retcode = flash_status_check (info, sector, tout, prompt);	switch (info->vendor) {	case CFI_CMDSET_INTEL_EXTENDED:	case CFI_CMDSET_INTEL_STANDARD:		if ((retcode != ERR_OK)		    && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {			retcode = ERR_INVAL;			printf ("Flash %s error at address %lx\n", prompt,				info->start[sector]);			if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {				puts ("Command Sequence Error.\n");			} else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {				puts ("Block Erase Error.\n");				retcode = ERR_NOT_ERASED;			} else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {				puts ("Locking Error\n");			}			if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {				puts ("Block locked.\n");				retcode = ERR_PROTECTED;			}			if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))				puts ("Vpp Low Error.\n");		}		flash_write_cmd (info, sector, 0, FLASH_CMD_RESET);		break;	default:		break;	}	return retcode;}/*----------------------------------------------------------------------- */static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c){#if defined(__LITTLE_ENDIAN)	unsigned short	w;	unsigned int	l;	unsigned long long ll;#endif	switch (info->portwidth) {	case FLASH_CFI_8BIT:		cword->c = c;		break;	case FLASH_CFI_16BIT:#if defined(__LITTLE_ENDIAN)		w = c;		w <<= 8;		cword->w = (cword->w >> 8) | w;#else		cword->w = (cword->w << 8) | c;#endif		break;	case FLASH_CFI_32BIT:#if defined(__LITTLE_ENDIAN)		l = c;		l <<= 24;		cword->l = (cword->l >> 8) | l;#else		cword->l = (cword->l << 8) | c;#endif		break;	case FLASH_CFI_64BIT:#if defined(__LITTLE_ENDIAN)		ll = c;		ll <<= 56;		cword->ll = (cword->ll >> 8) | ll;#else		cword->ll = (cword->ll << 8) | c;#endif		break;	}}/*----------------------------------------------------------------------- * make a proper sized command based on the port and chip widths */static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf){	int i;#if defined(__LITTLE_ENDIAN)	ushort stmpw;	uint   stmpi;#endif	uchar *cp = (uchar *) cmdbuf;	for (i = 0; i < info->portwidth; i++)		*cp++ = ((i + 1) % info->chipwidth) ? '\0' : cmd;#if defined(__LITTLE_ENDIAN)	switch (info->portwidth) {	case FLASH_CFI_8BIT:		break;	case FLASH_CFI_16BIT:		stmpw = *(ushort *) cmdbuf;		*(ushort *) cmdbuf = __swab16 (stmpw);		break;	case FLASH_CFI_32BIT:		stmpi = *(uint *) cmdbuf;		*(uint *) cmdbuf = __swab32 (stmpi);		break;	default:		puts ("WARNING: flash_make_cmd: unsuppported LittleEndian mode\n");		break;	}#endif}/* * Write a proper sized command to the correct address */static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd){	volatile cfiptr_t addr;	cfiword_t cword;	addr.cp = flash_make_addr (info, sect, offset);	flash_make_cmd (info, cmd, &cword);	switch (info->portwidth) {	case FLASH_CFI_8BIT:		debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr.cp, cmd,		       cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);		*addr.cp = cword.c;		break;	case FLASH_CFI_16BIT:		debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr.wp,		       cmd, cword.w,		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);		*addr.wp = cword.w;		break;	case FLASH_CFI_32BIT:		debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr.lp,		       cmd, cword.l,		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);		*addr.lp = cword.l;		break;	case FLASH_CFI_64BIT:#ifdef DEBUG		{

⌨️ 快捷键说明

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