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

📄 flash.c

📁 AT91RM9200的完整启动代码:包括loader, boot及U-boot三部分均已编译通过!欢迎下载使用!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (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 * * Hacked for the Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00 */#include <common.h>#include <mpc8260.h>#include <board/hymod/flash.h>flash_info_t flash_info[CFG_MAX_FLASH_BANKS];	/* info for FLASH chips *//*----------------------------------------------------------------------- * Protection Flags: */#define FLAG_PROTECT_SET	0x01#define FLAG_PROTECT_CLEAR	0x02/*----------------------------------------------------------------------- * Functions */#if 0static ulong flash_get_size (vu_long *addr, flash_info_t *info);static void flash_get_offsets (ulong base, flash_info_t *info);#endifstatic int write_word (flash_info_t *info, ulong dest, ulong data);/*----------------------------------------------------------------------- *//* * probe for the existence of flash at bank word address "addr" * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id */static intbank_probe_word(bank_addr_t addr){	int retval;	/* reset the flash */	*addr = BANK_CMD_RST;	/* check the manufacturer id */	*addr = BANK_CMD_RD_ID;	if (*BANK_ADDR_REG_MAN(addr) != BANK_RD_ID_MAN) {		retval = -1;		goto out;	}	/* check the device id */	*addr = BANK_CMD_RD_ID;	if (*BANK_ADDR_REG_DEV(addr) != BANK_RD_ID_DEV) {		retval = -2;		goto out;	}	retval = CFG_FLASH_TYPE;out:	/* reset the flash again */	*addr = BANK_CMD_RST;	return retval;}/* * probe for flash banks at address "base" and store info for any found * into flash_info entry "fip". Must find at least one bank. */static voidbank_probe(flash_info_t *fip, bank_addr_t base){	bank_addr_t addr, eaddr;	int nbanks;	fip->flash_id = FLASH_UNKNOWN;	fip->size = 0L;	fip->sector_count = 0;	addr = base;	eaddr = BANK_ADDR_BASE(addr, MAX_BANKS);	nbanks = 0;	while (addr < eaddr) {		bank_addr_t addrw, eaddrw, addrb;		int i, osc, nsc, curtype = -1;		addrw = addr;		eaddrw = BANK_ADDR_NEXT_WORD(addrw);		while (addrw < eaddrw) {			int thistype;#ifdef FLASH_DEBUG			printf("  probing for flash at addr 0x%08lx\n",				(unsigned long)addrw);#endif			if ((thistype = bank_probe_word(addrw++)) < 0)				goto out;			if (curtype < 0)				curtype = thistype;			else {				if (thistype != curtype) {					printf("Differing flash type found!\n");					goto out;				}			}		}		if (curtype < 0)			goto out;		/* bank exists - append info for this bank to *fip */		fip->flash_id = FLASH_MAN_INTEL|curtype;		fip->size += BANK_SIZE;		osc = fip->sector_count;		fip->sector_count += BANK_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 = BANK_ADDR_NEXT_BLK(addrb);		}		addr = BANK_ADDR_NEXT_BANK(addr);		nbanks++;	}out:	if (nbanks == 0)		panic("ERROR: no flash found at address 0x%08lx\n",			(unsigned long)base);}static voidbank_reset(flash_info_t *info, int sect){	bank_addr_t addrw, eaddrw;	addrw = (bank_addr_t)info->start[sect];	eaddrw = BANK_ADDR_NEXT_WORD(addrw);	while (addrw < eaddrw) {#ifdef FLASH_DEBUG		printf("  writing reset cmd to addr 0x%08lx\n",			(unsigned long)addrw);#endif		*addrw = BANK_CMD_RST;		addrw++;	}}static voidbank_erase_init(flash_info_t *info, int sect){	bank_addr_t addrw, saddrw, eaddrw;	int flag;#ifdef FLASH_DEBUG	printf("0x%08lx BANK_CMD_PROG\n", BANK_CMD_PROG);	printf("0x%08lx BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);	printf("0x%08lx BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);	printf("0x%08lx BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);	printf("0x%08lx BANK_CMD_RST\n", BANK_CMD_RST);	printf("0x%08lx BANK_STAT_RDY\n", BANK_STAT_RDY);	printf("0x%08lx BANK_STAT_ERR\n", BANK_STAT_ERR);#endif	saddrw = (bank_addr_t)info->start[sect];	eaddrw = BANK_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 = BANK_CMD_ERASE1;		*addrw = BANK_CMD_ERASE2;	}	/* re-enable interrupts if necessary */	if (flag)		enable_interrupts();}static intbank_erase_poll(flash_info_t *info, int sect){	bank_addr_t addrw, saddrw, eaddrw;	int sectdone, haderr;	saddrw = (bank_addr_t)info->start[sect];	eaddrw = BANK_ADDR_NEXT_WORD(saddrw);	sectdone = 1;	haderr = 0;	for (addrw = saddrw; addrw < eaddrw; addrw++) {		bank_word_t stat = *addrw;#ifdef FLASH_DEBUG		printf("  checking status at addr "			"0x%08lx [0x%08lx]\n",			(unsigned long)addrw, stat);#endif		if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)			sectdone = 0;		else if ((stat & BANK_STAT_ERR) != 0) {			printf(" failed on sector %d "				"(stat = 0x%08lx) at "				"address 0x%08lx\n",				sect, stat,				(unsigned long)addrw);			*addrw = BANK_CMD_CLR_STAT;			haderr = 1;		}	}	if (haderr)		return (-1);	else		return (sectdone);}static intbank_write_word(bank_addr_t addr, bank_word_t value){	bank_word_t stat;	ulong start;	int flag, retval;	/* Disable interrupts which might cause a timeout here */	flag = disable_interrupts();	*addr = BANK_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 & BANK_STAT_RDY) != BANK_STAT_RDY);	if ((stat & BANK_STAT_ERR) != 0) {		printf("flash program failed (stat = 0x%08lx) "			"at address 0x%08lx\n", (ulong)stat, (ulong)addr);		*addr = BANK_CMD_CLR_STAT;		retval = 3;	}done:	/* reset to read mode */	*addr = BANK_CMD_RST;	return (retval);}/*----------------------------------------------------------------------- */unsigned longflash_init(void){	int i;	/* Init: no FLASHes known */	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {		flash_info[i].flash_id = FLASH_UNKNOWN;	}	bank_probe(&flash_info[0], (bank_addr_t)CFG_FLASH_BASE);	/*	 * protect monitor and environment sectors	 */#if CFG_MONITOR_BASE == CFG_FLASH_BASE	(void)flash_protect(FLAG_PROTECT_SET,		      CFG_MONITOR_BASE,		      CFG_MONITOR_BASE+monitor_flash_len-1,		      &flash_info[0]);#endif#if defined(CFG_FLASH_ENV_ADDR)	(void)flash_protect(FLAG_PROTECT_SET,		      CFG_FLASH_ENV_ADDR,#if defined(CFG_FLASH_ENV_BUF)		      CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_BUF - 1,#else		      CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_SIZE - 1,#endif		      &flash_info[0]);#endif	return flash_info[0].size;}/*----------------------------------------------------------------------- */#if 0static voidflash_get_offsets(ulong base, flash_info_t *info){	int i;	/* set up sector start adress table */	if (info->flash_id & FLASH_BTYPE) {		/* set sector offsets for bottom boot block type	*/		info->start[0] = base + 0x00000000;		info->start[1] = base + 0x00008000;		info->start[2] = base + 0x0000C000;		info->start[3] = base + 0x00010000;		for (i = 4; i < info->sector_count; i++) {			info->start[i] = base + (i * 0x00020000) - 0x00060000;		}	} else {		/* set sector offsets for top boot block type		*/		i = info->sector_count - 1;		info->start[i--] = base + info->size - 0x00008000;		info->start[i--] = base + info->size - 0x0000C000;		info->start[i--] = base + info->size - 0x00010000;		for (; i >= 0; i--) {			info->start[i] = base + i * 0x00020000;		}	}}#endif	/* 0 */

⌨️ 快捷键说明

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