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

📄 intel32.c

📁 LUBBOCK板的BLOB
💻 C
字号:
/*
 * intel32.c: Intel 32 bit (2x 16 bit) flash driver
 *
 * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
 * Copyright (C) 1999  Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
 *
 * 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
 *
 */

#ident "$Id: intel32.c,v 1.4 2002/01/03 16:07:18 erikm Exp $"

#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif

#include <blob/errno.h>
#include <blob/flash.h>
#include <blob/util.h>
#include <blob/serial.h>


/* flash commands for two 16 bit intel flash chips */
#define READ_ARRAY		0x00FF00FF
#define ERASE_SETUP		0x00200020
#define ERASE_CONFIRM		0x00D000D0
#define	PGM_SETUP		0x00400040
#define	STATUS_READ		0x00700070
#define	STATUS_CLEAR		0x00500050
#define STATUS_BUSY		0x00800080
#define STATUS_ERASE_ERR	0x00200020
#define STATUS_PGM_ERR		0x00100010

#define CONFIG_SETUP		0x00600060
#define LOCK_SECTOR		0x00010001
#define UNLOCK_SECTOR		0x00D000D0
#define READ_CONFIG		0x00900090
#define LOCK_STATUS_LOCKED	0x00010001
#define LOCK_STATUS_LOCKEDDOWN	0x00020002




/* erases a flash block at the given address */
static int flash_erase_intel32(u32 *addr)
{
	u32 result;

	*addr = data_to_flash(STATUS_CLEAR);
	barrier();

	/* prepare for erase */
	*addr = data_to_flash(ERASE_SETUP);
	barrier();

	/* erase block */
	*addr = data_to_flash(ERASE_CONFIRM);
	barrier();

	/* status check */
	do {
		*addr = data_to_flash(STATUS_READ);
		barrier();
		result = data_from_flash(*addr);
		barrier();
	} while((~result & STATUS_BUSY) != 0);

	/* put flash back into Read Array mode */
	*addr = data_to_flash(READ_ARRAY);
	barrier();

	if((result & STATUS_ERASE_ERR) != 0) {
#ifdef BLOB_DEBUG
		SerialOutputString(__FUNCTION__ " failed, result=0x");
		SerialOutputHex(result);
		SerialOutputString(", addr=0x");
		SerialOutputHex((u32) addr);
		serial_write('\n');
#endif
		return -EFLASHERASE;
	}

	return 0;
}



/* write a flash block at a given location */
static int flash_write_intel32(u32 *dst, const u32* src)
{
	u32 result;

	*dst = data_to_flash(STATUS_CLEAR);
	barrier();

	/* setup flash for writing */
	*dst = data_to_flash(PGM_SETUP);
	barrier();

	/* write data */
	*dst = *src;
	barrier();

	/* status check */
	do {
		*dst = data_to_flash(STATUS_READ);
		barrier();

		result = data_from_flash(*dst);
		barrier();
	} while((~result & STATUS_BUSY) != 0);

	/* put flash back into Read Array mode */
	*dst = data_to_flash(READ_ARRAY);
	barrier();

	if(((result & STATUS_PGM_ERR) != 0) || (*dst != *src)) {
#ifdef BLOB_DEBUG
		SerialOutputString(__FUNCTION__ "failed, result=0x");
		SerialOutputHex(result);
		SerialOutputString(", addr=0x");
		SerialOutputHex((u32) dst);
		serial_write('\n');
#endif
		return -EFLASHPGM;
	}
	
	return 0;
}




static int flash_lock_block_intel32(u32 *blockStart)
{
	u32 result;

	*blockStart = data_to_flash(STATUS_CLEAR);
	barrier();

	*blockStart = data_to_flash(CONFIG_SETUP);
	barrier();
	*blockStart = data_to_flash(LOCK_SECTOR);
	barrier();

	*blockStart = data_to_flash(READ_ARRAY);
	barrier();

	/* status check */
	*blockStart = data_to_flash(STATUS_READ);
	barrier();

	result = data_from_flash(*blockStart);
	barrier();

	*blockStart = data_to_flash(READ_ARRAY);
	barrier();

	if ((result & STATUS_PGM_ERR) != 0) {
#ifdef FLASH_DEBUG
		SerialOutputString(__FUNCTION__ " failed at 0x");
		SerialOutputHex((u32) blockStart);
		SerialOutputString(", status=0x");
		SerialOutputHex((u32) result);
		SerialOutputByte('\n');
#endif
		return -EFLASHPGM;
	}

	return 0;
}




static int flash_unlock_block_intel32(u32 *blockStart)
{
	u32 result;

	*blockStart = data_to_flash(STATUS_CLEAR);
	barrier();

	*blockStart = data_to_flash(CONFIG_SETUP);
	barrier();
	*blockStart = data_to_flash(UNLOCK_SECTOR);
	barrier();

	*blockStart = data_to_flash(STATUS_READ);
	barrier();

	result = data_from_flash(*blockStart);
	barrier();

	*blockStart = data_to_flash(READ_ARRAY);
	barrier();

	if ((result & STATUS_PGM_ERR) != 0) {
#ifdef FLASH_DEBUG
		SerialOutputString(__FUNCTION__ " failed at 0x");
		SerialOutputHex((u32) blockStart);
		SerialOutputString(", status=0x");
		SerialOutputHex((u32) result);
		SerialOutputByte('\n');
#endif
		return -EFLASHPGM;
	}

	return 0;
}




static int flash_query_block_lock_intel32(u32 *blockStart)
{
	u32 result;

	*blockStart = data_to_flash(READ_CONFIG);
	barrier();
	result = data_from_flash(*(blockStart + 2));
	barrier();

	*blockStart = data_to_flash(READ_ARRAY);
	barrier();

#ifdef FLASH_DEBUG
	SerialOutputString(__FUNCTION__ ": status of block starting at 0x");
	SerialOutputHex((u32) blockStart);
	SerialOutputString(": 0x");
	SerialOutputHex((u32) result);
	SerialOutputByte('\n');
#endif

	return result & (LOCK_STATUS_LOCKED | LOCK_STATUS_LOCKEDDOWN);
}




/* flash driver structure */
flash_driver_t intel32_flash_driver = {
	erase:			flash_erase_intel32,
	write:			flash_write_intel32,
	lock_block:		flash_lock_block_intel32,
	unlock_block:		flash_unlock_block_intel32,
	query_block_lock:	flash_query_block_lock_intel32
};

⌨️ 快捷键说明

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