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

📄 flash.c

📁 U-boot源码 ARM7启动代码
💻 C
字号:
/* * U-boot - flash.c Flash driver for PSD4256GV * * Copyright (c) 2005-2007 Analog Devices Inc. * This file is based on BF533EzFlash.c originally written by Analog Devices, Inc. * * (C) Copyright 2000-2004 * 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., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA */#include <malloc.h>#include <config.h>#include <asm/io.h>#include "flash-defines.h"void flash_reset(void){	reset_flash();}unsigned long flash_get_size(ulong baseaddr, flash_info_t * info, int bank_flag){	int id = 0, i = 0;	static int FlagDev = 1;	id = get_codes();	if (FlagDev) {		FlagDev = 0;	}	info->flash_id = id;	switch (bank_flag) {	case 0:		for (i = PriFlashABegin; i < SecFlashABegin; i++)			info->start[i] = (baseaddr + (i * AFP_SectorSize1));		for (i = SecFlashABegin; i < NUM_SECTORS; i++)			info->start[i] =			    (baseaddr + SecFlashAOff +			     ((i - SecFlashABegin) * AFP_SectorSize2));		info->size = 0x400000;		info->sector_count = NUM_SECTORS;		break;	case 1:		info->start[0] = baseaddr + SecFlashASec1Off;		info->start[1] = baseaddr + SecFlashASec2Off;		info->start[2] = baseaddr + SecFlashASec3Off;		info->start[3] = baseaddr + SecFlashASec4Off;		info->size = 0x10000;		info->sector_count = 4;		break;	case 2:		info->start[0] = baseaddr + SecFlashBSec1Off;		info->start[1] = baseaddr + SecFlashBSec2Off;		info->start[2] = baseaddr + SecFlashBSec3Off;		info->start[3] = baseaddr + SecFlashBSec4Off;		info->size = 0x10000;		info->sector_count = 4;		break;	}	return (info->size);}unsigned long flash_init(void){	unsigned long size_b;	int i;	size_b = 0;	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {		flash_info[i].flash_id = FLASH_UNKNOWN;	}	size_b = flash_get_size(CFG_FLASH_BASE, &flash_info[0], 0);	if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b == 0) {		printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",		       size_b, size_b >> 20);	}	/* flash_protect (int flag, ulong from, ulong to, flash_info_t *info) */	(void)flash_protect(FLAG_PROTECT_SET, CFG_FLASH_BASE,			    (flash_info[0].start[2] - 1), &flash_info[0]);#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT)	(void)flash_protect(FLAG_PROTECT_SET, 0x203F0000, 0x203FFFFF,			    &flash_info[0]);#endif	return (size_b);}void flash_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) {	case (STM_ID_29W320EB & 0xFFFF):	case (STM_ID_29W320DB & 0xFFFF):		printf("ST Microelectronics ");		break;	default:		printf("Unknown Vendor: (0x%08X) ", info->flash_id);		break;	}	for (i = 0; i < info->sector_count; ++i) {		if ((i % 5) == 0)			printf("\n   ");		printf(" %08lX%s",		       info->start[i], info->protect[i] ? " (RO)" : "     ");	}	printf("\n");	return;}int flash_erase(flash_info_t * info, int s_first, int s_last){	int cnt = 0, i;	int prot, sect;	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");	cnt = s_last - s_first + 1;#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT)	printf("Erasing Flash locations, Please Wait\n");	for (i = s_first; i <= s_last; i++) {		if (info->protect[i] == 0) {	/* not protected */			if (erase_block_flash(i) < 0) {				printf("Error Sector erasing \n");				return FLASH_FAIL;			}		}	}#elif (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)	if (cnt == FLASH_TOT_SECT) {		printf("Erasing flash, Please Wait \n");		if (erase_flash() < 0) {			printf("Erasing flash failed \n");			return FLASH_FAIL;		}	} else {		printf("Erasing Flash locations, Please Wait\n");		for (i = s_first; i <= s_last; i++) {			if (info->protect[i] == 0) {	/* not protected */				if (erase_block_flash(i) < 0) {					printf("Error Sector erasing \n");					return FLASH_FAIL;				}			}		}	}#endif	printf("\n");	return FLASH_SUCCESS;}int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt){	int d;	if (addr % 2) {		read_flash(addr - 1 - CFG_FLASH_BASE, &d);		d = (int)((d & 0x00FF) | (*src++ << 8));		write_data(addr - 1, 2, (uchar *) & d);		write_data(addr + 1, cnt - 1, src);	} else		write_data(addr, cnt, src);	return FLASH_SUCCESS;}int write_data(long lStart, long lCount, uchar * pnData){	long i = 0;	unsigned long ulOffset = lStart - CFG_FLASH_BASE;	int d;	int nSector = 0;	int flag = 0;	if (lCount % 2) {		flag = 1;		lCount = lCount - 1;	}	for (i = 0; i < lCount - 1; i += 2, ulOffset += 2) {		get_sector_number(ulOffset, &nSector);		read_flash(ulOffset, &d);		if (d != 0xffff) {			printf			    ("Flash not erased at offset 0x%x Please erase to reprogram \n",			     ulOffset);			return FLASH_FAIL;		}		unlock_flash(ulOffset);		d = (int)(pnData[i] | pnData[i + 1] << 8);		write_flash(ulOffset, d);		if (poll_toggle_bit(ulOffset) < 0) {			printf("Error programming the flash \n");			return FLASH_FAIL;		}		if ((i > 0) && (!(i % AFP_SectorSize2)))			printf(".");	}	if (flag) {		get_sector_number(ulOffset, &nSector);		read_flash(ulOffset, &d);		if (d != 0xffff) {			printf			    ("Flash not erased at offset 0x%x Please erase to reprogram \n",			     ulOffset);			return FLASH_FAIL;		}		unlock_flash(ulOffset);		d = (int)(pnData[i] | (d & 0xFF00));		write_flash(ulOffset, d);		if (poll_toggle_bit(ulOffset) < 0) {			printf("Error programming the flash \n");			return FLASH_FAIL;		}	}	return FLASH_SUCCESS;}int write_flash(long nOffset, int nValue){	long addr;	addr = (CFG_FLASH_BASE + nOffset);	*(unsigned volatile short *)addr = nValue;	sync();#if (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)	if (icache_status())		udelay(CONFIG_CCLK_HZ / 1000000);#endif	return FLASH_SUCCESS;}int read_flash(long nOffset, int *pnValue){	unsigned short *pFlashAddr =	    (unsigned short *)(CFG_FLASH_BASE + nOffset);	*pnValue = *pFlashAddr;	return TRUE;}int poll_toggle_bit(long lOffset){	unsigned int u1, u2;	volatile unsigned long *FB =	    (volatile unsigned long *)(CFG_FLASH_BASE + lOffset);	while (1) {		u1 = *(volatile unsigned short *)FB;		u2 = *(volatile unsigned short *)FB;		u1 ^= u2;		if (!(u1 & 0x0040))			break;		if (!(u2 & 0x0020))			continue;		else {			u1 = *(volatile unsigned short *)FB;			u2 = *(volatile unsigned short *)FB;			u1 ^= u2;			if (!(u1 & 0x0040))				break;			else {				reset_flash();				return FLASH_FAIL;			}		}	}	return FLASH_SUCCESS;}void reset_flash(void){	write_flash(WRITESEQ1, RESET_VAL);	/* Wait for 10 micro seconds */	udelay(10);}int erase_flash(void){	write_flash(WRITESEQ1, WRITEDATA1);	write_flash(WRITESEQ2, WRITEDATA2);	write_flash(WRITESEQ3, WRITEDATA3);	write_flash(WRITESEQ4, WRITEDATA4);	write_flash(WRITESEQ5, WRITEDATA5);	write_flash(WRITESEQ6, WRITEDATA6);	if (poll_toggle_bit(0x0000) < 0)		return FLASH_FAIL;	return FLASH_SUCCESS;}int erase_block_flash(int nBlock){	long ulSectorOff = 0x0;	if ((nBlock < 0) || (nBlock > AFP_NumSectors))		return FALSE;	/* figure out the offset of the block in flash */	if ((nBlock >= 0) && (nBlock < SecFlashABegin))		ulSectorOff = nBlock * AFP_SectorSize1;	else if ((nBlock >= SecFlashABegin) && (nBlock < NUM_SECTORS))		ulSectorOff =		    SecFlashAOff + (nBlock - SecFlashABegin) * AFP_SectorSize2;	/* no such sector */	else		return FLASH_FAIL;	write_flash((WRITESEQ1 | ulSectorOff), WRITEDATA1);	write_flash((WRITESEQ2 | ulSectorOff), WRITEDATA2);	write_flash((WRITESEQ3 | ulSectorOff), WRITEDATA3);	write_flash((WRITESEQ4 | ulSectorOff), WRITEDATA4);	write_flash((WRITESEQ5 | ulSectorOff), WRITEDATA5);	write_flash(ulSectorOff, BlockEraseVal);	if (poll_toggle_bit(ulSectorOff) < 0)		return FLASH_FAIL;	printf(".");	return FLASH_SUCCESS;}void unlock_flash(long ulOffset){	unsigned long ulOffsetAddr = ulOffset;	ulOffsetAddr &= 0xFFFF0000;	write_flash((WRITESEQ1 | ulOffsetAddr), UNLOCKDATA1);	write_flash((WRITESEQ2 | ulOffsetAddr), UNLOCKDATA2);	write_flash((WRITESEQ3 | ulOffsetAddr), UNLOCKDATA3);}int get_codes(){	int dev_id = 0;	write_flash(WRITESEQ1, GETCODEDATA1);	write_flash(WRITESEQ2, GETCODEDATA2);	write_flash(WRITESEQ3, GETCODEDATA3);	read_flash(0x0402, &dev_id);	dev_id &= 0x0000FFFF;	reset_flash();	return dev_id;}void get_sector_number(long ulOffset, int *pnSector){	int nSector = 0;	long lMainEnd = 0x400000;	long lBootEnd = 0x10000;	/* sector numbers for the FLASH A boot sectors */	if (ulOffset < lBootEnd) {		nSector = (int)ulOffset / AFP_SectorSize1;	}	/* sector numbers for the FLASH B boot sectors */	else if ((ulOffset >= lBootEnd) && (ulOffset < lMainEnd)) {		nSector = ((ulOffset / (AFP_SectorSize2)) + 7);	}	/* if it is a valid sector, set it */	if ((nSector >= 0) && (nSector < AFP_NumSectors))		*pnSector = nSector;}

⌨️ 快捷键说明

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