📄 flash.c
字号:
//=============================================================================
//
// flash.c - Cyclone Diagnostics
//
//=============================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 2001 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden
// Contributors:
// Date: 2001-01-25
// Purpose:
// Description:
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
#include <redboot.h>
#ifdef CYGPKG_IO_FLASH
#include <cyg/io/flash.h>
#include "iq80310.h" /* 80310 chip set specific */
#include "7_segment_displays.h"
typedef unsigned char FLASH_TYPE;
#define MASK 0xff /* for 1 bank */
/* 28F016S5/28F640J3A Command Definitions - First Bus Cycle */
#define RESET_CMD (0xffffffff & MASK)
#define WRITE_TO_BUF_CMD (0xe8e8e8e8 & MASK)
#define WRITE_CONFIRM_CMD (0xd0d0d0d0 & MASK)
#define READ_ID_CMD (0x90909090 & MASK)
#define READ_STAT_REG (0x70707070 & MASK)
#define CLEAR_STAT_REG (0x50505050 & MASK)
#define ERASE_CMD (0x20202020 & MASK)
#define PROGRAM_CMD (0x40404040 & MASK)
#define BEP_SUSPEND (0xb0b0b0b0 & MASK)
#define BEP_RESUME (0xd0d0d0d0 & MASK)
#define LOCK_CMD (0x60606060 & MASK)
#define CLEAR_LOCK_BIT_SETUP (0x60606060 & MASK) /* 10/06/00 */
/* 28F016S5/28F640J3A Command Definitions - Second Bus Cycle */
#define ERASE_CONFIRM (0xd0d0d0d0 & MASK)
#define LOCK_BLOCK_CONFIRM (0x01010101 & MASK)
#define MASTER_LOCK_CONFIRM (0xf1f1f1f1 & MASK) /* DO NOT EVER set master enable bit!!! */
#define UNLOCK_BLOCK_CONFIRM (0xd0d0d0d0 & MASK)
#define CLEAR_LOCK_BIT_CONFIRM (0xd0d0d0d0 & MASK) /* 10/06/00 */
/* Flash category definitions */
#define SECTOR_PROG 0
#define BLOCK_PROG 1
/* status register bits */
#define WSM_READY (FLASH_TYPE) (1 << 7)
#define WSM_BUSY (FLASH_TYPE) (0 << 7)
#define BE_SUSPENDED (FLASH_TYPE) (1 << 6)
#define BE_COMPLETED (FLASH_TYPE) (0 << 6)
#define ERASE_UNLOCK_ERROR (FLASH_TYPE) (1 << 5)
#define ERASE_UNLOCK_SUCCESS (FLASH_TYPE) (0 << 5)
#define CLEAR_LOCK_BIT_ERROR (FLASH_TYPE) (1 << 5) /* 10/06/00 */
#define CLEAR_LOCK_BIT_SUCCESS (FLASH_TYPE) (0 << 5) /* 10/06/00 */
#define PROGRAM_LOCK_ERROR (FLASH_TYPE) (1 << 4)
#define PROGRAM_LOCK_SUCCESS (FLASH_TYPE) (0 << 4)
#define SET_LOCK_BIT_ERROR (FLASH_TYPE) (1 << 4) /* 10/17/00 */
#define SET_LOCK_BIT_SUCCESS (FLASH_TYPE) (0 << 4) /* 10/17/00 */
#define VPP_LOW_DETECT (FLASH_TYPE) (1 << 3)
#define VPP_OK (FLASH_TYPE) (0 << 3)
#define PROGRAM_SUSPENDED (FLASH_TYPE) (1 << 2)
#define PROGRAM_COMPLETED (FLASH_TYPE) (0 << 2)
#define DEVICE_PROTECTED (FLASH_TYPE) (1 << 1)
#define DEVICE_UNLOCKED (FLASH_TYPE) (0 << 1)
/* Other Intel 28F016S5/28F640J3A definitions */
#define CMD_SEQ_ERR (FLASH_TYPE) (ERASE_UNLOCK_ERROR | PROGRAM_LOCK_ERROR)
#define ALL_FLASH_STATUS (FLASH_TYPE) (0xfe)
#define UNKNOWN_ERR (FLASH_TYPE) (0xff)
#define TEST_BUF_LONGS 16384
#define TEST_BUF_CHARS 65536
#define MADE_BY_INTEL (0x89898989 & MASK) /* Manufacturer Code, read at address 0, note that address bit A0 is not used in x8 or x16 mode when obtaining identifier code */
/*#define I28F016S5 (0xAAAAAAAA & MASK)*/ /* 28F016S5 */
#define I28F640J3A (0x17171717 & MASK) /* Device Code, read at address 1, note that bit address A0 is not used in x8 or x16 mode when obtaining identifier code */
/*#define FLASH_BLOCK_SIZE 0x10000*/ /* 28F016S5 */
#define FLASH_BLOCK_SIZE 0x20000 /* 28F640J3A */
#define BLOCK_LOCKED 1
#define BLOCK_UNLOCKED 0
// First 4K page of flash at physical address zero is
// virtually mapped at address 0xd0000000.
#define FLASH_P2V(x) ((volatile FLASH_TYPE *)(((unsigned)(x) < 0x1000) ? \
((unsigned)(x) | 0xd0000000) : \
(unsigned)(x)))
unsigned long *flash_buffer = (unsigned long *)0xa1000000;
extern void _flushICache();
extern void _enableICache();
extern void _disableICache();
extern void _switchMMUpageTables();
extern void _usec_delay();
extern void _msec_delay();
unsigned long eeprom_size;
unsigned long flash_base;
ADDR flash_addr=FLASH_ADDR, eeprom_prog_first, eeprom_prog_last;
extern long hexIn();
extern char * sgets();
/* forward declarations */
void init_eeprom() RAM_FUNC_SECT;
int reserved_check(ADDR addr, unsigned long length) RAM_FUNC_SECT;
int is_eeprom(ADDR addr, unsigned long length) RAM_FUNC_SECT;
int check_eeprom(ADDR addr, unsigned long length) RAM_FUNC_SECT;
int lock_breeze() RAM_FUNC_SECT;
int check_bstat(int block_num) RAM_FUNC_SECT;
int set_all_lock_bits(void) RAM_FUNC_SECT; /* 10/11/00 added */
int clear_all_lock_bits(ADDR addr) RAM_FUNC_SECT; /* 10/06/00 added */
int check_erase_unlock(volatile FLASH_TYPE *flash) RAM_FUNC_SECT;
int check_op_status(int cmd, volatile FLASH_TYPE *flash) RAM_FUNC_SECT;
int erase_eeprom(ADDR addr, unsigned long length) RAM_FUNC_SECT;
int check_program_lock(volatile FLASH_TYPE *flash) RAM_FUNC_SECT;
int write_eeprom(ADDR start_addr, const void *data_arg, int data_size) RAM_FUNC_SECT;
void flash_test(void) RAM_FUNC_SECT;
void delay_and_flush(void) RAM_FUNC_SECT;
void do_nothing(void) RAM_FUNC_SECT;
void display_val(int num) RAM_FUNC_SECT;
void display_out (int msb_flag, unsigned char val) RAM_FUNC_SECT;
void check_lock_bit_status(void) RAM_FUNC_SECT;
#define MSB_DISPLAY_REG (volatile unsigned char *)0xfe840000
#define LSB_DISPLAY_REG (volatile unsigned char *)0xfe850000
void display_out (int msb_flag, unsigned char val)
{
/* unsigned char *ledPtr; */
volatile unsigned char *ledPtr;
unsigned char SevSegDecode;
if (msb_flag) ledPtr = MSB_DISPLAY_REG;
else ledPtr = LSB_DISPLAY_REG;
switch (val)
{
case 0:
SevSegDecode = ZERO;
break;
case 1:
SevSegDecode = ONE;
break;
case 2:
SevSegDecode = TWO;
break;
case 3:
SevSegDecode = THREE;
break;
case 4:
SevSegDecode = FOUR;
break;
case 5:
SevSegDecode = FIVE;
break;
case 6:
SevSegDecode = SIX;
break;
case 7:
SevSegDecode = SEVEN;
break;
case 8:
SevSegDecode = EIGHT;
break;
case 9:
SevSegDecode = NINE;
break;
case 10:
SevSegDecode = LETTER_A;
break;
case 11:
SevSegDecode = LETTER_B;
break;
case 12:
SevSegDecode = LETTER_C;
break;
case 13:
SevSegDecode = LETTER_D;
break;
case 14:
SevSegDecode = LETTER_E;
break;
case 15:
SevSegDecode = LETTER_F;
break;
default:
SevSegDecode = DECIMAL_POINT;
}
*ledPtr = SevSegDecode;
}
void display_val (int number)
{
unsigned char disp_val = number % 256;
unsigned char msb, lsb;
lsb = disp_val & 0x0f;
msb = (disp_val & 0xf0) >> 4;
display_out (0, lsb);
display_out (1, msb);
}
/* Used in write to buffer routine */
void do_nothing (void)
{
volatile int i;
for (i = 0; i < 50; i++); /* Rev 2.0B and Rev 2.0C */
/* for (i = 0; i < 100; i++); */ /* Rev 2.0A */
}
void delay_and_flush (void)
{
do_nothing();
_flushICache();
}
/********************************************************/
/* INIT FLASH */
/* */
/* This routine initializes the variables for timing */
/* with any board configuration. This is used to get */
/* exact timing every time. */
/********************************************************/
void init_eeprom()
{
#if 1
unsigned char MfgCode=MADE_BY_INTEL;
unsigned char DevCode=I28F640J3A;
eeprom_size = 0x800000;
#else
unsigned char MfgCode=0;
unsigned char DevCode=0;
flash_addr = FLASH_ADDR;
flash_base = FLASH_BASE_ADDR;
/* Set defaults */
eeprom_size = 0;
/* Note: the PCI-700 platform has only 1 memory bank */
/*
*( volatile unsigned char * ) FLASH_BASE_ADDR = RESET_CMD;
printf( "Wrote 1rst Read Array Command\n");
*/
*FLASH_P2V(FLASH_BASE_ADDR) = RESET_CMD; /* issue read array command */
delay_and_flush(); /* wait for Flash to re-enter Read Array mode */
*FLASH_P2V(FLASH_BASE_ADDR) = READ_ID_CMD; /* issue read id command */
MfgCode = *FLASH_P2V(FLASH_BASE_ADDR); /* read a manufacturer code at addr 0, address bit A0 is not used */
DevCode = *FLASH_P2V(DEV_CODE_ADDR); /* read a device code at addr 1 */
if (MfgCode == (MADE_BY_INTEL))
{
switch ( DevCode ) /* device code stored in addr 1, address bit A0 is not used, must shift 0x00000001<<1=0x00000002 */
{
case I28F640J3A:
eeprom_size += 0x800000 * FLASH_WIDTH; /* I28F640J3A */
break;
default:
break;
}
}
*FLASH_P2V(FLASH_BASE_ADDR) = READ_ID_CMD; /* issue 2nd read id command */
*FLASH_P2V(FLASH_BASE_ADDR) = RESET_CMD; /* issue read array command */
delay_and_flush(); /* wait for Flash to re-enter Read Array mode */
#endif
printf( "\nManufacturer Code = 0x%x\n", MfgCode);
printf( "Device Code = %x\n", DevCode);
printf( "Flash Memory size = 0x%x\n", eeprom_size);
return;
}
/********************************************************/
/* RESERVED AREA CHECK */
/* */
/* returns TRUE if the address falls into the */
/* reserved system area */
/* returns FALSE if the address is outside */
/* the reserved system area */
/********************************************************/
int reserved_check(ADDR addr, unsigned long length)
{
/* check start address */
if ( ( addr >= RESERVED_AREA1 ) && ( addr <= ( FLASH_BLK4_BASE_ADDR - 1 ) ) )
return TRUE;
/* must be outside the area */
else
return FALSE;
}
/********************************************************/
/* IS EEPROM */
/* Check if memory is Flash */
/* */
/* returns TRUE if it is; FALSE if not eeprom ; */
/* returns ERROR bad addr or partial eeprom */
/* */
/********************************************************/
int is_eeprom(ADDR addr, unsigned long length)
{
ADDR eeprom_end = flash_addr + eeprom_size - 1;
ADDR block_end = addr + length - 1;
/* Check for wrap: if the address and length given wrap past
* the end of memory, it is an error. */
if (block_end < addr)
return ERR;
if (addr >= flash_addr && block_end <= eeprom_end)
return TRUE;
if (addr > eeprom_end || block_end < flash_addr)
return FALSE;
/* If the block was partly within the Flash, it is an error. */
return ERR;
}
/********************************************************/
/* CHECK EEPROM */
/* Check if Flash is Blank */
/* */
/* returns OK if it is; returns ERROR and sets cmd_stat */
/* to an error code if memory region is not Flash or if */
/* it is not blank. */
/* */
/********************************************************/
int check_eeprom(ADDR addr, unsigned long length)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -