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

📄 flash.c

📁 U-BOOT,著名的Bootloader程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		info->sector_count = sectors;		info->size = sz;		*addr = (FPW) INTEL_RESET;	/* restore read mode */	} else {		int sect[] = CFG_ATMEL_SECT;		int sectsz[] = CFG_ATMEL_SECTSZ;		info->sector_count = 0;		info->size = 0;		for (i = 0; i < CFG_ATMEL_REGION; i++) {			info->sector_count += sect[i];			info->size += sect[i] * sectsz[i];		}		/* reset ID mode */		addr[0] = (FPWV) 0x00F000F0;	}	if (info->sector_count > CFG_MAX_FLASH_SECT) {		printf("** ERROR: sector count %d > max (%d) **\n",		       info->sector_count, CFG_MAX_FLASH_SECT);		info->sector_count = CFG_MAX_FLASH_SECT;	}	return (info->size);}int flash_cmd_rd(volatile u16 * addr, int index){	return (int)addr[index];}#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)int serial_flash_read_status(int chipsel){	u16 status;	dspi_tx(chipsel, 0x80, SER_RDSR);	dspi_rx();	dspi_tx(chipsel, 0x00, 0);	status = dspi_rx();	return status;}#endif/* * This function gets the u-boot flash sector protection status * (flash_info_t.protect[]) in sync with the sector protection * status stored in hardware. */void flash_sync_real_protect(flash_info_t * info){	int i;	switch (info->flash_id & FLASH_TYPEMASK) {	case FLASH_28F160C3B:	case FLASH_28F160C3T:	case FLASH_28F320C3B:	case FLASH_28F320C3T:	case FLASH_28F640C3B:	case FLASH_28F640C3T:		for (i = 0; i < info->sector_count; ++i) {			info->protect[i] = intel_sector_protected(info, i);		}		break;	default:		/* no h/w protect support */		break;	}}/* * checks if "sector" in bank "info" is protected. Should work on intel * strata flash chips 28FxxxJ3x in 8-bit mode. * Returns 1 if sector is protected (or timed-out while trying to read * protection status), 0 if it is not. */uchar intel_sector_protected(flash_info_t * info, ushort sector){	FPWV *addr;	FPWV *lock_conf_addr;	ulong start;	unsigned char ret;	/*	 * first, wait for the WSM to be finished. The rationale for	 * waiting for the WSM to become idle for at most	 * CFG_FLASH_ERASE_TOUT is as follows. The WSM can be busy	 * because of: (1) erase, (2) program or (3) lock bit	 * configuration. So we just wait for the longest timeout of	 * the (1)-(3), i.e. the erase timeout.	 */	/* wait at least 35ns (W12) before issuing Read Status Register */	/*udelay(1); */	addr = (FPWV *) info->start[sector];	*addr = (FPW) INTEL_STATUS;	start = get_timer(0);	while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) {		if (get_timer(start) > CFG_FLASH_UNLOCK_TOUT) {			*addr = (FPW) INTEL_RESET;	/* restore read mode */			printf("WSM busy too long, can't get prot status\n");			return 1;		}	}	/* issue the Read Identifier Codes command */	*addr = (FPW) INTEL_READID;	/* Intel example code uses offset of 4 for 8-bit flash */	lock_conf_addr = (FPWV *) info->start[sector];	ret = (lock_conf_addr[INTEL_CFI_LOCK] & (FPW) INTEL_PROTECT) ? 1 : 0;	/* put flash back in read mode */	*addr = (FPW) INTEL_RESET;	return ret;}int flash_erase(flash_info_t * info, int s_first, int s_last){	int flag, prot, sect;	ulong type, start, last;	int rcode = 0, flashtype = 0;#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)	int count;	u16 status;#endif	if ((s_first < 0) || (s_first > s_last)) {		if (info->flash_id == FLASH_UNKNOWN)			printf("- missing\n");		else			printf("- no sectors to erase\n");		return 1;	}	type = (info->flash_id & FLASH_VENDMASK);	switch (type) {	case FLASH_MAN_ATM:		flashtype = 1;		break;	case FLASH_MAN_INTEL:		flashtype = 2;		break;#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)	case FLASH_MAN_STM:		flashtype = 3;		break;#endif	default:		type = (info->flash_id & FLASH_VENDMASK);		printf("Can't erase unknown flash type %08lx - aborted\n",		       info->flash_id);		return 1;	}	prot = 0;	for (sect = s_first; sect <= s_last; ++sect) {		if (info->protect[sect]) {			prot++;		}	}	if (prot)		printf("- Warning: %d protected sectors will not be erased!\n",		       prot);	else		printf("\n");	start = get_timer(0);	last = start;#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)	/* Perform bulk erase */	if (flashtype == 3) {		if ((s_last - s_first) == (CFG_STM_SECT - 1)) {			if (prot == 0) {				dspi_tx(ser_flash_cs, 0x00, SER_WREN);				dspi_rx();				status = serial_flash_read_status(ser_flash_cs);				if (((status & 0x9C) != 0)				    && ((status & 0x02) != 0x02)) {					printf("Can't erase flash\n");					return 1;				}				dspi_tx(ser_flash_cs, 0x00, SER_BULK_ERASE);				dspi_rx();				count = 0;				start = get_timer(0);				do {					status =					    serial_flash_read_status					    (ser_flash_cs);					if (count++ > 0x10000) {						spin_wheel();						count = 0;					}					if (get_timer(start) >					    CFG_FLASH_ERASE_TOUT) {						printf("Timeout\n");						return 1;					}				} while (status & 0x01);				printf("\b. done\n");				return 0;			} else if (prot == CFG_STM_SECT) {				return 1;			}		}	}#endif	/* Start erase on unprotected sectors */	for (sect = s_first; sect <= s_last; sect++) {		if (info->protect[sect] == 0) {	/* not protected */			FPWV *addr = (FPWV *) (info->start[sect]);			int min = 0;			printf(".");			/* arm simple, non interrupt dependent timer */			start = get_timer(0);			switch (flashtype) {			case 1:				{					FPWV *base;	/* first address in bank */					FPWV *atmeladdr;					flag = disable_interrupts();					atmeladdr = (FPWV *) addr;	/* concatenate to 8 bit */					base = (FPWV *) (CFG_ATMEL_BASE);	/* First sector */					base[FLASH_CYCLE1] = (u8) 0x00AA00AA;	/* unlock */					base[FLASH_CYCLE2] = (u8) 0x00550055;	/* unlock */					base[FLASH_CYCLE1] = (u8) 0x00800080;	/* erase mode */					base[FLASH_CYCLE1] = (u8) 0x00AA00AA;	/* unlock */					base[FLASH_CYCLE2] = (u8) 0x00550055;	/* unlock */					*atmeladdr = (u8) 0x00300030;	/* erase sector */					if (flag)						enable_interrupts();					while ((*atmeladdr & (u8) 0x00800080) !=					       (u8) 0x00800080) {						if (get_timer(start) >						    CFG_FLASH_ERASE_TOUT) {							printf("Timeout\n");							*atmeladdr = (u8) 0x00F000F0;	/* reset to read mode */							rcode = 1;							break;						}					}					*atmeladdr = (u8) 0x00F000F0;	/* reset to read mode */					break;				}			case 2:				{					*addr = (FPW) INTEL_READID;					min = addr[INTEL_CFI_TERB] & 0xff;					min = 1 << min;	/* ms */					min = (min / info->sector_count) * 1000;					/* start erase block */					*addr = (FPW) INTEL_CLEAR;	/* clear status register */					*addr = (FPW) INTEL_ERASE;	/* erase setup */					*addr = (FPW) INTEL_CONFIRM;	/* erase confirm */					while ((*addr & (FPW) INTEL_FINISHED) !=					       (FPW) INTEL_FINISHED) {						if (get_timer(start) >						    CFG_FLASH_ERASE_TOUT) {							printf("Timeout\n");							*addr = (FPW) INTEL_SUSERASE;	/* suspend erase     */							*addr = (FPW) INTEL_RESET;	/* reset to read mode */							rcode = 1;							break;						}					}					*addr = (FPW) INTEL_RESET;	/* resest to read mode          */					break;				}#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)			case 3:				{					u8 sec = ((ulong) addr >> 16) & 0xFF;					dspi_tx(ser_flash_cs, 0x00, SER_WREN);					dspi_rx();					status =					    serial_flash_read_status					    (ser_flash_cs);					if (((status & 0x9C) != 0)					    && ((status & 0x02) != 0x02)) {						printf("Error Programming\n");						return 1;					}					dspi_tx(ser_flash_cs, 0x80,						SER_SECT_ERASE);					dspi_tx(ser_flash_cs, 0x80, sec);					dspi_tx(ser_flash_cs, 0x80, 0);					dspi_tx(ser_flash_cs, 0x00, 0);					dspi_rx();					dspi_rx();					dspi_rx();					dspi_rx();					do {						status =						    serial_flash_read_status						    (ser_flash_cs);						if (get_timer(start) >						    CFG_FLASH_ERASE_TOUT) {							printf("Timeout\n");							return 1;						}					} while (status & 0x01);					break;				}#endif			}	/* switch (flashtype) */		}	}	printf(" done\n");	return rcode;}int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt){	int count;	if (info->flash_id == FLASH_UNKNOWN)		return 4;	switch (info->flash_id & FLASH_VENDMASK) {	case FLASH_MAN_ATM:		{			u16 data = 0;			int bytes;	/* number of bytes to program in current word */			int left;	/* number of bytes left to program */			int i, res;			for (left = cnt, res = 0;			     left > 0 && res == 0;			     addr += sizeof(data), left -=			     sizeof(data) - bytes) {				bytes = addr & (sizeof(data) - 1);				addr &= ~(sizeof(data) - 1);				/* combine source and destination data so can program				 * an entire word of 16 or 32 bits				 */				for (i = 0; i < sizeof(data); i++) {					data <<= 8;					if (i < bytes || i - bytes >= left)						data += *((uchar *) addr + i);					else						data += *src++;				}				data = (data >> 8) | (data << 8);				res = write_word_atm(info, (FPWV *) addr, data);			}			return res;		}		/* case FLASH_MAN_ATM */	case FLASH_MAN_INTEL:		{			ulong cp, wp;			u16 data;			int i, l, rc, port_width;			/* get lower word aligned address */			wp = addr;			port_width = sizeof(FPW);			/*			 * handle unaligned start bytes			 */			if ((l = addr - wp) != 0) {				data = 0;				for (i = 0, cp = wp; i < l; ++i, ++cp) {					data = (data << 8) | (*(uchar *) cp);				}				for (; i < port_width && cnt > 0; ++i) {					data = (data << 8) | *src++;					--cnt;					++cp;				}				for (; cnt == 0 && i < port_width; ++i, ++cp)					data = (data << 8) | (*(uchar *) cp);				if ((rc = write_data(info, wp, data)) != 0)					return (rc);				wp += port_width;			}			if (cnt > WR_BLOCK) {				/*				 * handle word aligned part				 */				count = 0;				while (cnt >= WR_BLOCK) {

⌨️ 快捷键说明

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