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

📄 flash.c

📁 U BOOT源码
💻 C
字号:
/* * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <board/cogent/flash.h>flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/#if defined(CFG_ENV_IS_IN_FLASH)# ifndef  CFG_ENV_ADDR#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)# endif# ifndef  CFG_ENV_SIZE#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE# endif# ifndef  CFG_ENV_SECT_SIZE#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE# endif#endif/*----------------------------------------------------------------------- * Functions */static int write_word (flash_info_t *info, ulong dest, ulong data);/*----------------------------------------------------------------------- */#if defined(CONFIG_CMA302)/* * probe for the existence of flash at address "addr" * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id */static intc302f_probe_word(c302f_addr_t addr){	/* reset the flash */	*addr = C302F_BNK_CMD_RST;	/* check the manufacturer id */	*addr = C302F_BNK_CMD_RD_ID;	if (*C302F_BNK_ADDR_MAN(addr) != C302F_BNK_RD_ID_MAN)		return 1;	/* check the device id */	*addr = C302F_BNK_CMD_RD_ID;	if (*C302F_BNK_ADDR_DEV(addr) != C302F_BNK_RD_ID_DEV)		return 2;#ifdef FLASH_DEBUG	{		int i;		printf("\nMaster Lock Config = 0x%08lx\n",			*C302F_BNK_ADDR_CFGM(addr));		for (i = 0; i < C302F_BNK_NBLOCKS; i++)			printf("Block %2d Lock Config = 0x%08lx\n",				i, *C302F_BNK_ADDR_CFG(i, addr));	}#endif	/* reset the flash again */	*addr = C302F_BNK_CMD_RST;	return 0;}/* * probe for Cogent CMA302 flash module at address "base" and store * info for any found into flash_info entry "fip". Must find at least * one bank. */static voidc302f_probe(flash_info_t *fip, c302f_addr_t base){	c302f_addr_t addr, eaddr;	int nbanks;	fip->size = 0L;	fip->sector_count = 0;	addr = base;	eaddr = C302F_BNK_ADDR_BASE(addr, C302F_MAX_BANKS);	nbanks = 0;	while (addr < eaddr) {		c302f_addr_t addrw, eaddrw, addrb;		int i, osc, nsc;		addrw = addr;		eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);		while (addrw < eaddrw)			if (c302f_probe_word(addrw++) != 0)				goto out;		/* bank exists - append info for this bank to *fip */		fip->flash_id = FLASH_MAN_INTEL|FLASH_28F008S5;		fip->size += C302F_BNK_SIZE;		osc = fip->sector_count;		fip->sector_count += C302F_BNK_NBLOCKS;		if ((nsc = fip->sector_count) >= CFG_MAX_FLASH_SECT)			panic("Too many sectors in flash at address 0x%08lx\n",				(unsigned long)base);		addrb = addr;		for (i = osc; i < nsc; i++) {			fip->start[i] = (ulong)addrb;			fip->protect[i] = 0;			addrb = C302F_BNK_ADDR_NEXT_BLK(addrb);		}		addr = C302F_BNK_ADDR_NEXT_BNK(addr);		nbanks++;	}out:	if (nbanks == 0)		panic("ERROR: no flash found at address 0x%08lx\n",			(unsigned long)base);}static voidc302f_reset(flash_info_t *info, int sect){	c302f_addr_t addrw, eaddrw;	addrw = (c302f_addr_t)info->start[sect];	eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);	while (addrw < eaddrw) {#ifdef FLASH_DEBUG		printf("  writing reset cmd to addr 0x%08lx\n",			(unsigned long)addrw);#endif		*addrw = C302F_BNK_CMD_RST;		addrw++;	}}static voidc302f_erase_init(flash_info_t *info, int sect){	c302f_addr_t addrw, saddrw, eaddrw;	int flag;#ifdef FLASH_DEBUG	printf("0x%08lx C302F_BNK_CMD_PROG\n", C302F_BNK_CMD_PROG);	printf("0x%08lx C302F_BNK_CMD_ERASE1\n", C302F_BNK_CMD_ERASE1);	printf("0x%08lx C302F_BNK_CMD_ERASE2\n", C302F_BNK_CMD_ERASE2);	printf("0x%08lx C302F_BNK_CMD_CLR_STAT\n", C302F_BNK_CMD_CLR_STAT);	printf("0x%08lx C302F_BNK_CMD_RST\n", C302F_BNK_CMD_RST);	printf("0x%08lx C302F_BNK_STAT_RDY\n", C302F_BNK_STAT_RDY);	printf("0x%08lx C302F_BNK_STAT_ERR\n", C302F_BNK_STAT_ERR);#endif	saddrw = (c302f_addr_t)info->start[sect];	eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);#ifdef FLASH_DEBUG	printf("erasing sector %d, start addr = 0x%08lx "		"(bank next word addr = 0x%08lx)\n", sect,		(unsigned long)saddrw, (unsigned long)eaddrw);#endif	/* Disable intrs which might cause a timeout here */	flag = disable_interrupts();	for (addrw = saddrw; addrw < eaddrw; addrw++) {#ifdef FLASH_DEBUG		printf("  writing erase cmd to addr 0x%08lx\n",			(unsigned long)addrw);#endif		*addrw = C302F_BNK_CMD_ERASE1;		*addrw = C302F_BNK_CMD_ERASE2;	}	/* re-enable interrupts if necessary */	if (flag)		enable_interrupts();}static intc302f_erase_poll(flash_info_t *info, int sect){	c302f_addr_t addrw, saddrw, eaddrw;	int sectdone, haderr;	saddrw = (c302f_addr_t)info->start[sect];	eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);	sectdone = 1;	haderr = 0;	for (addrw = saddrw; addrw < eaddrw; addrw++) {		c302f_word_t stat = *addrw;#ifdef FLASH_DEBUG		printf("  checking status at addr "			"0x%08lx [0x%08lx]\n",			(unsigned long)addrw, stat);#endif		if ((stat & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY)			sectdone = 0;		else if ((stat & C302F_BNK_STAT_ERR) != 0) {			printf(" failed on sector %d "				"(stat = 0x%08lx) at "				"address 0x%08lx\n",				sect, stat,				(unsigned long)addrw);			*addrw = C302F_BNK_CMD_CLR_STAT;			haderr = 1;		}	}	if (haderr)		return (-1);	else		return (sectdone);}static intc302f_write_word(c302f_addr_t addr, c302f_word_t value){	c302f_word_t stat;	ulong start;	int flag, retval;	/* Disable interrupts which might cause a timeout here */	flag = disable_interrupts();	*addr = C302F_BNK_CMD_PROG;	*addr = value;	/* re-enable interrupts if necessary */	if (flag)		enable_interrupts();	retval = 0;	/* data polling for D7 */	start = get_timer (0);	do {		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {			retval = 1;			goto done;		}		stat = *addr;	} while ((stat & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY);	if ((stat & C302F_BNK_STAT_ERR) != 0) {		printf("flash program failed (stat = 0x%08lx) "			"at address 0x%08lx\n", (ulong)stat, (ulong)addr);		*addr = C302F_BNK_CMD_CLR_STAT;		retval = 3;	}done:	/* reset to read mode */	*addr = C302F_BNK_CMD_RST;	return (retval);}#endif	/* CONFIG_CMA302 */unsigned longflash_init(void){	unsigned long total;	int i;	flash_info_t *fip;	/* Init: no FLASHes known */	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {		flash_info[i].flash_id = FLASH_UNKNOWN;	}	fip = &flash_info[0];	total = 0L;#if defined(CONFIG_CMA302)	c302f_probe(fip, (c302f_addr_t)CFG_FLASH_BASE);	total += fip->size;	fip++;#endif#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)	/* not yet ...	cmbf_probe(fip, (cmbf_addr_t)CMA_MB_FLASH_BASE);	total += fip->size;	fip++;	*/#endif	/*	 * protect monitor and environment sectors	 */#if CFG_MONITOR_BASE == CFG_FLASH_BASE	flash_protect(FLAG_PROTECT_SET,		      CFG_MONITOR_BASE,		      CFG_MONITOR_BASE+monitor_flash_len-1,		      &flash_info[0]);#endif#ifdef	CFG_ENV_IS_IN_FLASH	/* ENV protection ON by default */	flash_protect(FLAG_PROTECT_SET,		      CFG_ENV_ADDR,		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,		      &flash_info[0]);#endif	return total;}/*----------------------------------------------------------------------- */voidflash_print_info(flash_info_t *info){	int i;	if (info->flash_id == FLASH_UNKNOWN) {		printf ("missing or unknown FLASH type\n");		return;	}	switch (info->flash_id & FLASH_VENDMASK) {	case FLASH_MAN_INTEL:	printf ("INTEL ");		break;	default:		printf ("Unknown Vendor ");	break;	}	switch (info->flash_id & FLASH_TYPEMASK) {	case FLASH_28F008S5:	printf ("28F008S5\n");				break;	default:		printf ("Unknown Chip Type\n");				break;	}	printf ("  Size: %ld MB in %d Sectors\n",		info->size >> 20, info->sector_count);	printf ("  Sector Start Addresses:");	for (i=0; i<info->sector_count; ++i) {		if ((i % 4) == 0)			printf ("\n   ");		printf (" %2d - %08lX%s", i,			info->start[i],			info->protect[i] ? " (RO)" : "     "		);	}	printf ("\n");	return;}/*----------------------------------------------------------------------- *//*----------------------------------------------------------------------- *//* * The following code cannot be run from FLASH! */intflash_erase(flash_info_t *info, int s_first, int s_last){	int prot, sect, haderr;	ulong start, now, last;	void (*erase_init)(flash_info_t *, int);	int (*erase_poll)(flash_info_t *, int);	void (*reset)(flash_info_t *, int);	int rcode = 0;#ifdef FLASH_DEBUG	printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"		"  Bank # %d: ", s_last - s_first + 1, s_first, s_last,		(info - flash_info) + 1);	flash_print_info(info);#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;	}	switch (info->flash_id) {#if defined(CONFIG_CMA302)	case FLASH_MAN_INTEL|FLASH_28F008S5:		erase_init = c302f_erase_init;		erase_poll = c302f_erase_poll;		reset = c302f_reset;		break;#endif#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)	case FLASH_MAN_INTEL|FLASH_28F800_B:	case FLASH_MAN_AMD|FLASH_AM29F800B:		/* not yet ...		erase_init = cmbf_erase_init;		erase_poll = cmbf_erase_poll;		reset = cmbf_reset;		break;		*/#endif	default:		printf ("Flash type %08lx not supported - 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 sector%s will not be erased!\n",			prot, (prot > 1 ? "s" : ""));	}	start = get_timer (0);	last = 0;	haderr = 0;	for (sect = s_first; sect <= s_last; sect++) {		if (info->protect[sect] == 0) {	/* not protected */			ulong estart;			int sectdone;			(*erase_init)(info, sect);			/* wait at least 80us - let's wait 1 ms */			udelay (1000);			estart = get_timer(start);			do {				now = get_timer(start);				if (now - estart > CFG_FLASH_ERASE_TOUT) {					printf ("Timeout (sect %d)\n", sect);					haderr = 1;					break;				}#ifndef FLASH_DEBUG				/* show that we're waiting */				if ((now - last) > 1000) { /* every second */					putc ('.');					last = now;				}#endif				sectdone = (*erase_poll)(info, sect);				if (sectdone < 0) {					haderr = 1;					break;				}			} while (!sectdone);			if (haderr)				break;		}	}	if (haderr > 0) {		printf (" failed\n");	        rcode = 1;	}	else		printf (" done\n");	/* reset to read mode */	for (sect = s_first; sect <= s_last; sect++) {		if (info->protect[sect] == 0) {	/* not protected */			(*reset)(info, sect);		}	}	return rcode;}/*----------------------------------------------------------------------- * Copy memory to flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased * 3 - write error */intwrite_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt){	ulong cp, wp, data;	int i, l, rc;	ulong start, now, last;	wp = (addr & ~3);	/* get lower word aligned address */	/*	 * 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<4 && cnt>0; ++i) {			data = (data << 8) | *src++;			--cnt;			++cp;		}		for (; cnt==0 && i<4; ++i, ++cp) {			data = (data << 8) | (*(uchar *)cp);		}		if ((rc = write_word(info, wp, data)) != 0) {			return (rc);		}		wp += 4;	}	/*	 * handle word aligned part	 */	start = get_timer (0);	last = 0;	while (cnt >= 4) {		data = 0;		for (i=0; i<4; ++i) {			data = (data << 8) | *src++;		}		if ((rc = write_word(info, wp, data)) != 0) {			return (rc);		}		wp  += 4;		cnt -= 4;		/* show that we're waiting */		now = get_timer(start);		if ((now - last) > 1000) {	/* every second */			putc ('.');			last = now;		}	}	if (cnt == 0) {		return (0);	}	/*	 * handle unaligned tail bytes	 */	data = 0;	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {		data = (data << 8) | *src++;		--cnt;	}	for (; i<4; ++i, ++cp) {		data = (data << 8) | (*(uchar *)cp);	}	return (write_word(info, wp, data));}/*----------------------------------------------------------------------- * Write a word to Flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased * 3 - write error */static intwrite_word(flash_info_t *info, ulong dest, ulong data){	int retval;	/* Check if Flash is (sufficiently) erased */	if ((*(ulong *)dest & data) != data) {		return (2);	}	switch (info->flash_id) {#if defined(CONFIG_CMA302)	case FLASH_MAN_INTEL|FLASH_28F008S5:		retval = c302f_write_word((c302f_addr_t)dest, (c302f_word_t)data);		break;#endif#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)	case FLASH_MAN_INTEL|FLASH_28F800_B:	case FLASH_MAN_AMD|FLASH_AM29F800B:		/* not yet ...		retval = cmbf_write_word((cmbf_addr_t)dest, (cmbf_word_t)data);		*/		retval = 3;		break;#endif	default:		printf ("Flash type %08lx not supported - aborted\n",			info->flash_id);		retval = 3;		break;	}	return (retval);}/*----------------------------------------------------------------------- */

⌨️ 快捷键说明

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