📄 flash_toshiba.c
字号:
/* * File: flash_toshiba.c * * An implementation of a flash utility for most flash chips that support * the CFI command set 2 specification. Also supports specific chips * including the 2 Mbyte Toshiba chip (TC58FB160FT-xx) or the very similar, * but larger, 8 Mbyte Fujitsu MBM29DL323B chip. * * See Also * flash.h * * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * 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., * 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "flash.h"#include "types.h"#include "util.h"#include "io.h"#include "memconfig.h"static int total_sectors = 0; // set in flash_init()#define CMDMAX 10unsigned char cmd[CMDMAX];#if BSPCONF_FLASH_TYPE == CFI_CMDSET_2#define TOTAL_SECT 256 // a number bigger than largest chipstatic int sect_sizes[TOTAL_SECT]; // filled in by flash_init()#elif BSPCONF_FLASH_TYPE == TOSHIBA_TC58FB160FT#define FLASH_ID 0x00980043#define NUM_CHIP_SECT 35#define NUM_CHIPS 1#define TOTAL_SECT (NUM_CHIPS*NUM_CHIP_SECT)static const int sect_sizes[NUM_CHIP_SECT] = { 0x4000, 0x2000, 0x2000, 0x8000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000};#elif BSPCONF_FLASH_TYPE == FUJITSU_MBM29DL323B#define FLASH_ID 0x00042253#define NUM_CHIP_SECT 71#define NUM_CHIPS 1#define TOTAL_SECT (NUM_CHIPS*NUM_CHIP_SECT)static const int sect_sizes[NUM_CHIP_SECT] = { 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000 , 0x2000 , 0x2000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000};#elif BSPCONF_FLASH_TYPE == AMD_AM29DL164DT#define FLASH_ID 0x00012233#define NUM_CHIP_SECT 39#define NUM_CHIPS 1#define TOTAL_SECT (NUM_CHIPS*NUM_CHIP_SECT)static const int sect_sizes[NUM_CHIP_SECT] = { 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x02000, 0x02000, 0x02000, 0x02000, 0x02000, 0x02000, 0x02000, 0x02000};#elif BSPCONF_FLASH_TYPE == FUJITSU_29LV320T#define FLASH_ID 0x000422F6#define NUM_CHIP_SECT 71#define NUM_CHIPS 1#define TOTAL_SECT (NUM_CHIPS*NUM_CHIP_SECT)static const int sect_sizes[NUM_CHIP_SECT] = { 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000 , 0x2000 , 0x2000};//###########################################################//// This is OUR TYPE !!!! ////############################################################elif BSPCONF_FLASH_TYPE == HYNIX_HY29LD320B#define SST 0#define ST 1#define M29W320DB 0x22CA#define SST39VF320 0x2783//***********************************************************// ST (M29W320DB) : // VENDOR_ID = 0x0020// FLASH_ID = 0x22CB// NUM_CHIP_SECT = 67// TOTAL_SECT = 67 (NUM_CHIP_SECT * NUM_CHIPS)//***********************************************************// SST (SST39VF320) :// VENDOR_ID = 0x00BF// FLASH_ID = 0x2783// NUM_CHIP_SECT = 64// TOTAL_SECT = 64 (NUM_CHIP_SECT * NUM_CHIPS)//***********************************************************#define NUM_CHIPS 1#define MAX_SECT_NUM 80#define SST39VF320_NUM_SECT 64#define M29W320DB_NUM_SECT 67static const int M29W320DB_SECT_SIZES[MAX_SECT_NUM] = { 0x4000, 0x2000, 0x2000, 0x8000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000,};static const int SST39VF320_SECT_SIZES[MAX_SECT_NUM] = { 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000,};static int VENDOR_ID, FLASH_ID;static int NUM_CHIP_SECT, TOTAL_SECT;//############################################################else #error Must specify a supported BSPCONF_FLASH part.#endiftypedef struct { int start_addr; int end_addr;} sect_info_t;sect_info_t sect_info[MAX_SECT_NUM*NUM_CHIPS];struct erase_region_info { int sectors; int size;};#define MAX_REGIONS_PER_FLASH 8//***************************************************************// Routine:// Description: Returns the starting address for flash block// containing block_address//***************************************************************unsigned short *get_start_address(unsigned short *block_address){ int i; for (i=0; i<total_sectors; i++) { if (((unsigned short *)sect_info[i].start_addr >= block_address) && ((unsigned short *)sect_info[i].start_addr <= block_address)) { return((unsigned short *)sect_info[i].start_addr); } } return(0);}//***************************************************************// Routine:// Description: Returns the ending address for flash block// containing block_address//***************************************************************unsigned short *get_end_address(unsigned short *block_address){ int i; for (i=0; i<total_sectors; i++) { if (((unsigned short *)sect_info[i].start_addr >= block_address) && ((unsigned short *)sect_info[i].start_addr <= block_address)) { return((unsigned short *)sect_info[i].end_addr); } } return(0);}//***************************************************************// Routine:// Description: returns true if the block has been erased//***************************************************************static int verify_block_erased(unsigned short *block_addr, int print_err){ volatile unsigned short *addr; volatile unsigned short contents; unsigned short *start_addr; unsigned short *end_addr; int err = false; start_addr = get_start_address(block_addr); end_addr = get_end_address(block_addr); for (addr=start_addr; addr<end_addr; addr++) { contents = *addr; if (contents != 0xFFFF) { err = true; break; } } if (err && print_err) { util_printf("Error: address range %X - %X not erased: %X=%x\n", start_addr, end_addr, addr, contents); } return(!err);}#if defined(BSPCONF_BTLDR_MEMMAP_DEBUG) || (BSPCONF_FLASH_TYPE == CFI_CMDSET_2)//***************************************************************// Routine:// Description://***************************************************************static void enable_read_mode(){ volatile unsigned short *addr; addr = (unsigned short *) BSPCONF_FLASH_BASE; if (FLASH_ID == M29W320DB) { *addr = 0xF0; } else if (FLASH_ID == SST39VF320) { addr[0x5555] = 0xAA; addr[0x2AAA] = 0x55; addr[0x5555] = 0xF0; } io_delay(100);}//***************************************************************// Routine:// Description: Returns true if flash// part supports CFI//***************************************************************static int cfi_supported(void){ volatile unsigned short *addr; int read_array[3]; addr = (unsigned short *) BSPCONF_FLASH_BASE; //--------------------------------------------- // 1st try !! (SST) //--------------------------------------------- addr[0x5555] = 0xAA; addr[0x2AAA] = 0x55; addr[0x5555] = 0x98; io_delay (100); read_array[0] = addr[0x10]; read_array[1] = addr[0x11]; read_array[2] = addr[0x12]; if ((read_array[0]=='Q') && (read_array[1]=='R') && (read_array[2]=='Y')) return SST39VF320; // FOUND !!! :-) //--------------------------------------------- // 2nd try !! (ST) //--------------------------------------------- addr[0x55] = 0x98; /* Enter read array mode */ read_array[0] = addr[0x10]; read_array[1] = addr[0x11]; read_array[2] = addr[0x12]; if ((read_array[0]=='Q') && (read_array[1]=='R') && (read_array[2]=='Y')) return M29W320DB; // FOUND !!! :-) return 0; // NOT FOUND !!! :-(}//***************************************************************// Routine:// Description: returns true if device// code read, false if chip doesn't support CFI//***************************************************************int read_device_codes(unsigned long *Code){ unsigned short regval; volatile unsigned short *addr; int ret_value; addr = (unsigned short *) BSPCONF_FLASH_BASE; ret_value = cfi_supported (); if (ret_value == 0) { *Code = 0; return 0; } //-------------------------------------- // set flash device info //-------------------------------------- switch (ret_value) { case SST39VF320: // SST VENDOR_ID = SST; NUM_CHIP_SECT = SST39VF320_NUM_SECT; break; case M29W320DB: // ST VENDOR_ID = ST; NUM_CHIP_SECT = M29W320DB_NUM_SECT; break; } FLASH_ID = ret_value; TOTAL_SECT = NUM_CHIP_SECT * NUM_CHIPS; enable_read_mode(); if (FLASH_ID == M29W320DB) { addr[0x555] = 0xAA; addr[0x2AA] = 0x55; addr[0x555] = 0x90; } else if (FLASH_ID == SST39VF320) { addr[0x5555] = 0xAA; addr[0x2AAA] = 0x55; addr[0x5555] = 0x90; } io_delay (100); util_printf ("----------------------------------------------------\n"); ///////////////////////////////////////////////// // Manufacturer's Code ///////////////////////////////////////////////// regval = addr[0]; util_printf (" Manufacturer's ID = 0x%x \t", regval); switch (regval) { case 0x20: // ST util_printf ("[ST]\n"); break; case 0xBF: // SST util_printf ("[SST]\n"); break; } ///////////////////////////////////////////////// // Device's Code ///////////////////////////////////////////////// *Code = regval << 16; regval = addr[1]; util_printf (" Device ID = 0x%x \t", regval); switch (regval) { case 0x22CB: // ST (M29W320DB) util_printf ("[M29W320DB]\n"); break; case 0x2783: // SST (SST39VF320) util_printf ("[SST39VF320]\n"); break; case 0x235B: // SST (SST39VF3201) util_printf ("[SST39VF3201]\n"); break; case 0x235A: // SST (SST39VF3202) util_printf ("[SST39VF3202]\n"); break; } util_printf ("----------------------------------------------------\n"); *Code = *Code | regval; enable_read_mode(); return(1);}//***************************************************************// Routine:// Description: returns true if chip supports CFI. array elements// from CFI_START_ADDR to CFI_END_ADDR filled with CFI read array data.// Returns: false if chip doesn't support CFI.//***************************************************************int read_cfi_array(unsigned short array[], int array_size){ volatile unsigned short *addr; int i; addr = (unsigned short *) BSPCONF_FLASH_BASE; if ( array_size < (CFI_END_ADDR +1)) { util_printf("read_cfi_array: ERROR array too small\n"); return(0); } if ( ! cfi_supported() ) { return(0); } enable_read_mode(); if (FLASH_ID == M29W320DB) { addr[0x55] = 0x98; /* Enter read array mode */ } else if (FLASH_ID == SST39VF320)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -