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

📄 flash.c

📁 OMAP2530 uboot source code
💻 C
字号:
/* * U-boot - flash.c Flash driver for PSD4256GV * * Copyright (c) 2005 blackfin.uclinux.org * 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., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#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)	{#ifdef DEBUG		printf("Device ID of the Flash is %x\n", id);#endif		FlagDev = 0;	}	info->flash_id = id;	switch (bank_flag) {	case 0:		for (i = PriFlashABegin; i < SecFlashABegin; i++)			info->start[i] = (baseaddr + (i * AFP_SectorSize1));		info->size = 0x200000;		info->sector_count = 32;		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_b0, size_b1, size_b2;	int i;	size_b0 = size_b1 = size_b2 = 0;#ifdef DEBUG	printf("Flash Memory Start 0x%x\n", CFG_FLASH_BASE);	printf("Memory Map for the Flash\n");	printf("0x20000000 - 0x200FFFFF Flash A Primary (1MB)\n");	printf("0x20100000 - 0x201FFFFF Flash B Primary (1MB)\n");	printf("0x20200000 - 0x2020FFFF Flash A Secondary (64KB)\n");	printf("0x20280000 - 0x2028FFFF Flash B Secondary (64KB)\n");	printf("Please type command flinfo for information on Sectors \n");#endif	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {		flash_info[i].flash_id = FLASH_UNKNOWN;	}	size_b0 = flash_get_size(CFG_FLASH0_BASE, &flash_info[0], 0);	size_b1 = flash_get_size(CFG_FLASH0_BASE, &flash_info[1], 1);	size_b2 = flash_get_size(CFG_FLASH0_BASE, &flash_info[2], 2);	if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {		printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",			size_b0, size_b0 >> 20);	}	(void)flash_protect(FLAG_PROTECT_SET,CFG_FLASH0_BASE,(flash_info[0].start[2] - 1),&flash_info[0]);	return (size_b0 + size_b1 + size_b2);}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 FLASH_PSD4256GV:		printf("ST Microelectronics ");		break;	default:		printf("Unknown Vendor ");		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 (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, info->start[i]) < 0) {					printf("Error Sector erasing \n");					return FLASH_FAIL;				}			}		}	}	return FLASH_SUCCESS;}int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt){	int ret;	ret = write_data(addr, cnt, 1, (int *) src);	if(ret == FLASH_FAIL)		return ERR_NOT_ERASED;	return FLASH_SUCCESS;}int write_data(long lStart, long lCount, long lStride, int *pnData){	long i = 0;	int j = 0;	unsigned long ulOffset = lStart - CFG_FLASH_BASE;	int d;	int iShift = 0;	int iNumWords = 2;	int nLeftover = lCount % 4;	int nSector = 0;	for (i = 0; (i < lCount / 4) && (i < BUFFER_SIZE); i++) {		for (iShift = 0, j = 0; (j < iNumWords);			j++, ulOffset += (lStride * 2)) {			if ((ulOffset >= INVALIDLOCNSTART)			&& (ulOffset < INVALIDLOCNEND)) {				printf("Invalid locations, Try writing to another location \n");				return FLASH_FAIL;			}			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);			if(write_flash(ulOffset, (pnData[i] >> iShift)) < 0) {				printf("Error programming the flash \n");				return FLASH_FAIL;			}			iShift += 16;		}	}	if (nLeftover > 0) {		if ((ulOffset >= INVALIDLOCNSTART)			&& (ulOffset < INVALIDLOCNEND))				return FLASH_FAIL;		get_sector_number(ulOffset, &nSector);		read_flash(ulOffset,&d);		if(d != 0xffff) {			printf("Flash already programmed. Please erase to reprogram \n");			printf("uloffset = 0x%x \t d = 0x%x\n",ulOffset,d);			return FLASH_FAIL;		}		unlock_flash(ulOffset);		if(write_flash(ulOffset, pnData[i]) < 0) {			printf("Error programming the flash \n");			return FLASH_FAIL;		}	}	return FLASH_SUCCESS;}int read_data(long ulStart, long lCount, long lStride, int *pnData){	long i = 0;	int j = 0;	long ulOffset = ulStart;	int iShift = 0;	int iNumWords = 2;	int nLeftover = lCount % 4;	int nHi, nLow;	int nSector = 0;	for (i = 0; (i < lCount / 4) && (i < BUFFER_SIZE); i++) {		for (iShift = 0, j = 0; j < iNumWords; j += 2) {			if ((ulOffset >= INVALIDLOCNSTART)				&& (ulOffset < INVALIDLOCNEND))					return FLASH_FAIL;			get_sector_number(ulOffset, &nSector);			read_flash(ulOffset, &nLow);			ulOffset += (lStride * 2);			read_flash(ulOffset, &nHi);			ulOffset += (lStride * 2);			pnData[i] = (nHi << 16) | nLow;		}	}	if (nLeftover > 0) {		if ((ulOffset >= INVALIDLOCNSTART)			&& (ulOffset < INVALIDLOCNEND))				return FLASH_FAIL;		get_sector_number(ulOffset, &nSector);		read_flash(ulOffset, &pnData[i]);	}	return FLASH_SUCCESS;}int write_flash(long nOffset, int nValue){	long addr;	addr = (CFG_FLASH_BASE + nOffset);	asm("ssync;");	*(unsigned volatile short *) addr = nValue;	asm("ssync;");	if(poll_toggle_bit(nOffset) < 0)		return FLASH_FAIL;	return FLASH_SUCCESS;}int read_flash(long nOffset, int *pnValue){	int nValue = 0x0;	long addr = (CFG_FLASH_BASE + nOffset);	if (nOffset != 0x2)		reset_flash();	asm("ssync;");	nValue = *(volatile unsigned short *) addr;	asm("ssync;");	*pnValue = nValue;	return TRUE;}int poll_toggle_bit(long lOffset){	unsigned int u1,u2;	unsigned long timeout = 0xFFFFFFFF;	volatile unsigned long *FB = (volatile unsigned long *)(0x20000000 + lOffset);	while(1) {		if(timeout < 0)			break;		u1 = *(volatile unsigned short *)FB;		u2 = *(volatile unsigned short *)FB;		if((u1 & 0x0040) == (u2 & 0x0040))			return FLASH_SUCCESS;		if((u2 & 0x0020) == 0x0000)			continue;		u1 = *(volatile unsigned short *)FB;		if((u2 & 0x0040) == (u1 & 0x0040))			return FLASH_SUCCESS;		else {			reset_flash();			return FLASH_FAIL;		}		timeout--;	}	printf("Time out occured \n");	if(timeout <0)	return FLASH_FAIL;}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;	write_flash(SecFlashAOff + WRITESEQ1, WRITEDATA1);	write_flash(SecFlashAOff + WRITESEQ2, WRITEDATA2);	write_flash(SecFlashAOff + WRITESEQ3, WRITEDATA3);	write_flash(SecFlashAOff + WRITESEQ4, WRITEDATA4);	write_flash(SecFlashAOff + WRITESEQ5, WRITEDATA5);	write_flash(SecFlashAOff + WRITESEQ6, WRITEDATA6);	if(poll_toggle_bit(SecFlashASec1Off) < 0)		return FLASH_FAIL;	write_flash(PriFlashBOff + WRITESEQ1, WRITEDATA1);	write_flash(PriFlashBOff + WRITESEQ2, WRITEDATA2);	write_flash(PriFlashBOff + WRITESEQ3, WRITEDATA3);	write_flash(PriFlashBOff + WRITESEQ4, WRITEDATA4);	write_flash(PriFlashBOff + WRITESEQ5, WRITEDATA5);	write_flash(PriFlashBOff + WRITESEQ6, WRITEDATA6);	if(poll_toggle_bit(PriFlashBOff) <0)		return FLASH_FAIL;	write_flash(SecFlashBOff + WRITESEQ1, WRITEDATA1);	write_flash(SecFlashBOff + WRITESEQ2, WRITEDATA2);	write_flash(SecFlashBOff + WRITESEQ3, WRITEDATA3);	write_flash(SecFlashBOff + WRITESEQ4, WRITEDATA4);	write_flash(SecFlashBOff + WRITESEQ5, WRITEDATA5);	write_flash(SecFlashBOff + WRITESEQ6, WRITEDATA6);	if(poll_toggle_bit(SecFlashBOff) < 0)		return FLASH_FAIL;	return FLASH_SUCCESS;}int erase_block_flash(int nBlock, unsigned long address){	long ulSectorOff = 0x0;	if ((nBlock < 0) || (nBlock > AFP_NumSectors))		return FALSE;	ulSectorOff = (address - CFG_FLASH_BASE);	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;	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(0x0002, &dev_id);	dev_id &= 0x00FF;	reset_flash();	return dev_id;}void get_sector_number(long ulOffset, int *pnSector){	int nSector = 0;	if (ulOffset >= SecFlashAOff) {		if ((ulOffset < SecFlashASec1Off)			&& (ulOffset < SecFlashASec2Off)) {				nSector = SECT32;		} else if ((ulOffset >= SecFlashASec2Off)			&& (ulOffset < SecFlashASec3Off)) {				nSector = SECT33;		} else if ((ulOffset >= SecFlashASec3Off)			&& (ulOffset < SecFlashASec4Off)) {				nSector = SECT34;		} else if ((ulOffset >= SecFlashASec4Off)			&& (ulOffset < SecFlashAEndOff)) {				nSector = SECT35;		}	} else if (ulOffset >= SecFlashBOff) {		if ((ulOffset < SecFlashBSec1Off)			&& (ulOffset < SecFlashBSec2Off)) {				nSector = SECT36;		}		if ((ulOffset < SecFlashBSec2Off)			&& (ulOffset < SecFlashBSec3Off)) {				nSector = SECT37;		}		if ((ulOffset < SecFlashBSec3Off)			&& (ulOffset < SecFlashBSec4Off)) {				nSector = SECT38;		}		if ((ulOffset < SecFlashBSec4Off)			&& (ulOffset < SecFlashBEndOff)) {				nSector = SECT39;		}	} else if ((ulOffset >= PriFlashAOff) && (ulOffset < SecFlashAOff)) {		nSector = ulOffset & 0xffff0000;		nSector = ulOffset >> 16;		nSector = nSector & 0x000ff;	}	if ((nSector >= 0) && (nSector < AFP_NumSectors)) {		*pnSector = nSector;	}}

⌨️ 快捷键说明

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