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

📄 flash.c

📁 u-boot-1.1.6 源码包
💻 C
字号:
/* * * Copyright (c) 2004	Cucy Systems (http://www.cucy.com) * Curt Brune <curt@cucy.com> * * 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 <asm/hardware.h>#include <flash.h>flash_info_t flash_info[CFG_MAX_FLASH_BANKS];typedef enum {	FLASH_DEV_U9_512KB = 0,	FLASH_DEV_U7_2MB = 1} FLASH_DEV;#define FLASH_DQ7		(0x80)#define FLASH_DQ5		(0x20)#define PROG_ADDR		(0xAAA)#define SETUP_ADDR		(0xAAA)#define ID_ADDR			(0xAAA)#define UNLOCK_ADDR1		(0xAAA)#define UNLOCK_ADDR2		(0x555)#define UNLOCK_CMD1		(0xAA)#define UNLOCK_CMD2		(0x55)#define ERASE_SUSPEND_CMD	(0xB0)#define ERASE_RESUME_CMD	(0x30)#define RESET_CMD		(0xF0)#define ID_CMD			(0x90)#define SELECT_CMD		(0x90)#define CHIPERASE_CMD		(0x10)#define BYPASS_CMD		(0x20)#define SECERASE_CMD		(0x30)#define PROG_CMD		(0xa0)#define SETUP_CMD		(0x80)#if 0#define WRITE_UNLOCK(addr) { \	PUT__U8( addr + UNLOCK_ADDR1, UNLOCK_CMD1); \	PUT__U8( addr + UNLOCK_ADDR2, UNLOCK_CMD2); \}/* auto select command */#define CMD_ID(addr) WRITE_UNLOCK(addr); { \	PUT__U8( addr + ID_ADDR, ID_CMD); \}#define CMD_RESET(addr) WRITE_UNLOCK(addr); { \	PUT__U8( addr + ID_ADDR, RESET_CMD); \}#define CMD_ERASE_SEC(base, addr) WRITE_UNLOCK(base); \	PUT__U8( base + SETUP_ADDR, SETUP_CMD); \	WRITE_UNLOCK(base); \	PUT__U8( addr, SECERASE_CMD);#define CMD_ERASE_CHIP(base) WRITE_UNLOCK(base); \	PUT__U8( base + SETUP_ADDR, SETUP_CMD); \	WRITE_UNLOCK(base); \	PUT__U8( base + SETUP_ADDR, CHIPERASE_CMD);/* prepare for bypass programming */#define CMD_UNLOCK_BYPASS(addr) WRITE_UNLOCK(addr); { \	PUT__U8( addr + ID_ADDR, 0x20); \}/* terminate bypass programming */#define CMD_BYPASS_RESET(addr) { \	PUT__U8(addr, 0x90); \	PUT__U8(addr, 0x00); \}#endifinline static void FLASH_CMD_UNLOCK (FLASH_DEV dev, u32 base){	switch (dev) {	case FLASH_DEV_U7_2MB:		PUT__U8 (base + 0xAAA, 0xAA);		PUT__U8 (base + 0x555, 0x55);		break;	case FLASH_DEV_U9_512KB:		PUT__U8 (base + 0x555, 0xAA);		PUT__U8 (base + 0x2AA, 0x55);		break;	}}inline static void FLASH_CMD_SELECT (FLASH_DEV dev, u32 base){	switch (dev) {	case FLASH_DEV_U7_2MB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0xAAA, SELECT_CMD);		break;	case FLASH_DEV_U9_512KB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0x555, SELECT_CMD);		break;	}}inline static void FLASH_CMD_RESET (FLASH_DEV dev, u32 base){	switch (dev) {	case FLASH_DEV_U7_2MB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0xAAA, RESET_CMD);		break;	case FLASH_DEV_U9_512KB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0x555, RESET_CMD);		break;	}}inline static void FLASH_CMD_ERASE_SEC (FLASH_DEV dev, u32 base, u32 addr){	switch (dev) {	case FLASH_DEV_U7_2MB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0xAAA, SETUP_CMD);		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (addr, SECERASE_CMD);		break;	case FLASH_DEV_U9_512KB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0x555, SETUP_CMD);		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (addr, SECERASE_CMD);		break;	}}inline static void FLASH_CMD_ERASE_CHIP (FLASH_DEV dev, u32 base){	switch (dev) {	case FLASH_DEV_U7_2MB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0xAAA, SETUP_CMD);		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base, CHIPERASE_CMD);		break;	case FLASH_DEV_U9_512KB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0x555, SETUP_CMD);		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base, CHIPERASE_CMD);		break;	}}inline static void FLASH_CMD_UNLOCK_BYPASS (FLASH_DEV dev, u32 base){	switch (dev) {	case FLASH_DEV_U7_2MB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0xAAA, BYPASS_CMD);		break;	case FLASH_DEV_U9_512KB:		FLASH_CMD_UNLOCK (dev, base);		PUT__U8 (base + 0x555, BYPASS_CMD);		break;	}}inline static void FLASH_CMD_BYPASS_RESET (FLASH_DEV dev, u32 base){	PUT__U8 (base, SELECT_CMD);	PUT__U8 (base, 0x0);}/* poll for flash command completion */static u16 _flash_poll (FLASH_DEV dev, u32 addr, u16 data, ulong timeOut){	u32 done = 0;	ulong t0;	u16 error = 0;	volatile u16 flashData;	data = data & 0xFF;	t0 = get_timer (0);	while (get_timer (t0) < timeOut) {		/*	for( i = 0; i < POLL_LOOPS; i++) { */		/*  Read the Data */		flashData = GET__U8 (addr);		/*  FLASH_DQ7 = Data? */		if ((flashData & FLASH_DQ7) == (data & FLASH_DQ7)) {			done = 1;			break;		}		/*  Check Timeout (FLASH_DQ5==1) */		if (flashData & FLASH_DQ5) {			/*  Read the Data */			flashData = GET__U8 (addr);			/*  FLASH_DQ7 = Data? */			if (!((flashData & FLASH_DQ7) == (data & FLASH_DQ7))) {				printf ("_flash_poll(): FLASH_DQ7 & flashData not equal to write value\n");				error = ERR_PROG_ERROR;			}			FLASH_CMD_RESET (dev, addr);			done = 1;			break;		}		/*  spin delay */		udelay (10);	}	/*  error update */	if (!done) {		printf ("_flash_poll(): Timeout\n");		error = ERR_TIMOUT;	}	/*  Check the data */	if (!error) {		/*  Read the Data */		flashData = GET__U8 (addr);		if (flashData != data) {			error = ERR_PROG_ERROR;			printf ("_flash_poll(): flashData(0x%04x) not equal to data(0x%04x)\n",				flashData, data);		}	}	return error;}/*----------------------------------------------------------------------- */static int _flash_check_protection (flash_info_t * info, int s_first, int s_last){	int sect, prot = 0;	for (sect = s_first; sect <= s_last; sect++)		if (info->protect[sect]) {			printf ("  Flash sector %d protected.\n", sect);			prot++;		}	return prot;}static int _detectFlash (FLASH_DEV dev, u32 base, u8 venId, u8 devId){	u32 baseAddr = base | CACHE_DISABLE_MASK;	u8 vendorId, deviceId;	/*	printf(__FUNCTION__"(): detecting flash @ 0x%08x\n", base); */	/* Send auto select command and read manufacturer info */	FLASH_CMD_SELECT (dev, baseAddr);	vendorId = GET__U8 (baseAddr);	FLASH_CMD_RESET (dev, baseAddr);	/* Send auto select command and read device info */	FLASH_CMD_SELECT (dev, baseAddr);	if (dev == FLASH_DEV_U7_2MB) {		deviceId = GET__U8 (baseAddr + 2);	} else if (dev == FLASH_DEV_U9_512KB) {		deviceId = GET__U8 (baseAddr + 1);	} else {		return 0;	}	FLASH_CMD_RESET (dev, baseAddr);	/* printf (__FUNCTION__"(): found vendorId 0x%04x, deviceId 0x%04x\n",		vendorId, deviceId);	 */	return (vendorId == venId) && (deviceId == devId);}/****************************************************************************** * * Public u-boot interface functions below * *****************************************************************************//*************************************************************************** * * Flash initialization * * This board has two banks of flash, but the base addresses depend on * how the board is jumpered. * * The two flash types are: * *   AMD Am29LV160DB (2MB) sectors layout 16KB, 2x8KB, 32KB, 31x64KB * *   AMD Am29LV040B  (512KB)  sectors: 8x64KB *****************************************************************************/unsigned long flash_init (void){	flash_info_t *info;	u16 i;	u32 flashtest;	s16 amd160 = -1;	u32 amd160base = 0;#if CFG_MAX_FLASH_BANKS == 2	s16 amd040 = -1;	u32 amd040base = 0;#endif	/* configure PHYS_FLASH_1 */	if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_1, 0x1, 0x49)) {		amd160 = 0;		amd160base = PHYS_FLASH_1;#if CFG_MAX_FLASH_BANKS == 1	}#else		if (_detectFlash		    (FLASH_DEV_U9_512KB, PHYS_FLASH_2, 0x1, 0x4F)) {			amd040 = 1;			amd040base = PHYS_FLASH_2;		} else {			printf (__FUNCTION__				"(): Unable to detect PHYS_FLASH_2: 0x%08x\n",				PHYS_FLASH_2);		}	} else if (_detectFlash (FLASH_DEV_U9_512KB, PHYS_FLASH_1, 0x1, 0x4F)) {		amd040 = 0;		amd040base = PHYS_FLASH_1;		if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_2, 0x1, 0x49)) {			amd160 = 1;			amd160base = PHYS_FLASH_2;		} else {			printf (__FUNCTION__				"(): Unable to detect PHYS_FLASH_2: 0x%08x\n",				PHYS_FLASH_2);		}	}#endif	else {		printf ("flash_init(): Unable to detect PHYS_FLASH_1: 0x%08x\n",			PHYS_FLASH_1);	}	/* Configure AMD Am29LV160DB (2MB) */	info = &flash_info[amd160];	info->flash_id = FLASH_DEV_U7_2MB;	info->sector_count = 35;	info->size = 2 * 1024 * 1024;	/* 2MB */	/* 1*16K Boot Block	   2*8K Parameter Block	   1*32K Small Main Block */	info->start[0] = amd160base;	info->start[1] = amd160base + 0x4000;	info->start[2] = amd160base + 0x6000;	info->start[3] = amd160base + 0x8000;	for (i = 1; i < info->sector_count; i++)		info->start[3 + i] = amd160base + i * (64 * 1024);	for (i = 0; i < info->sector_count; i++) {		/* Write auto select command sequence and query sector protection */		FLASH_CMD_SELECT (info->flash_id,				  info->start[i] | CACHE_DISABLE_MASK);		flashtest =			GET__U8 (((info->start[i] + 4) | CACHE_DISABLE_MASK));		FLASH_CMD_RESET (info->flash_id,				 amd160base | CACHE_DISABLE_MASK);		info->protect[i] = (flashtest & 0x0001);	}	/*	 * protect monitor and environment sectors in 2MB flash	 */	flash_protect (FLAG_PROTECT_SET,		       amd160base, amd160base + monitor_flash_len - 1, info);	flash_protect (FLAG_PROTECT_SET,		       CFG_ENV_ADDR, CFG_ENV_ADDR + CFG_ENV_SIZE - 1, info);#if CFG_MAX_FLASH_BANKS == 2	/* Configure AMD Am29LV040B (512KB) */	info = &flash_info[amd040];	info->flash_id = FLASH_DEV_U9_512KB;	info->sector_count = 8;	info->size = 512 * 1024;	/* 512KB, 8 x 64KB */	for (i = 0; i < info->sector_count; i++) {		info->start[i] = amd040base + i * (64 * 1024);		/* Write auto select command sequence and query sector protection */		FLASH_CMD_SELECT (info->flash_id,				  info->start[i] | CACHE_DISABLE_MASK);		flashtest =			GET__U8 (((info->start[i] + 2) | CACHE_DISABLE_MASK));		FLASH_CMD_RESET (info->flash_id,				 amd040base | CACHE_DISABLE_MASK);		info->protect[i] = (flashtest & 0x0001);	}#endif	return flash_info[0].size#if CFG_MAX_FLASH_BANKS == 2		+ flash_info[1].size#endif		;}void flash_print_info (flash_info_t * info){	int i;	if (info->flash_id == FLASH_DEV_U7_2MB) {		printf ("AMD Am29LV160DB (2MB) 16KB,2x8KB,32KB,31x64KB\n");	} else if (info->flash_id == FLASH_DEV_U9_512KB) {		printf ("AMD Am29LV040B	 (512KB) 8x64KB\n");	} else {		printf ("Unknown flash_id ...\n");		return;	}	printf ("  Size: %ld KB in %d Sectors\n",		info->size >> 10, info->sector_count);	printf ("  Sector Start Addresses:");	for (i = 0; i < info->sector_count; i++) {		if ((i % 4) == 0)			printf ("\n   ");		printf (" S%02d @ 0x%08lX%s", i,			info->start[i], info->protect[i] ? " !" : "  ");	}	printf ("\n");}int flash_erase (flash_info_t * info, int s_first, int s_last){	u16 i, error = 0;	printf ("\n");	/* check flash protection bits */	if (_flash_check_protection (info, s_first, s_last)) {		printf ("  Flash erase aborted due to protected sectors\n");		return ERR_PROTECTED;	}	if ((s_first < info->sector_count) && (s_first <= s_last)) {		for (i = s_first; i <= s_last && !error; i++) {			printf ("  Erasing Sector %d @ 0x%08lx ... ", i,				info->start[i]);			/* bypass the cache to access the flash memory */			FLASH_CMD_ERASE_SEC (info->flash_id,					     (info->					      start[0] | CACHE_DISABLE_MASK),					     (info->					      start[i] | CACHE_DISABLE_MASK));			/* look for sector to become 0xFF after erase */			error = _flash_poll (info->flash_id,					     info->					     start[i] | CACHE_DISABLE_MASK,					     0xFF, CFG_FLASH_ERASE_TOUT);			FLASH_CMD_RESET (info->flash_id,					 (info->					  start[0] | CACHE_DISABLE_MASK));			printf ("done\n");			if (error) {				break;			}		}	} else		error = ERR_INVAL;	return error;}int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt){	u16 error = 0, i;	u32 n;	u8 *bp, *bps;	/*  Write Setup */	/* bypass the cache to access the flash memory */	FLASH_CMD_UNLOCK_BYPASS (info->flash_id,				 (info->start[0] | CACHE_DISABLE_MASK));	/*  Write the Data to Flash */	bp = (u8 *) (addr | CACHE_DISABLE_MASK);	bps = (u8 *) src;	for (n = 0; n < cnt && !error; n++, bp++, bps++) {		if (!(n % (cnt / 15))) {			printf (".");		}		/*  write the flash command for flash memory */		*bp = 0xA0;		/*  Write the data */		*bp = *bps;		/*  Check if the write is done */		for (i = 0; i < 0xff; i++);		error = _flash_poll (info->flash_id, (u32) bp, *bps,				     CFG_FLASH_WRITE_TOUT);		if (error) {			return error;		}	}	/*  Reset the Flash Mode to read */	FLASH_CMD_BYPASS_RESET (info->flash_id, info->start[0]);	printf (" ");	return error;}

⌨️ 快捷键说明

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