📄 flash_toshiba.c
字号:
{ addr[0x5555] = 0xAA; /* Enter read array mode */ addr[0x2AAA] = 0x55; /* Enter read array mode */ addr[0x5555] = 0x98; /* Enter read array mode */ } for ( i=CFI_START_ADDR; i <= CFI_END_ADDR; i++) { array[i] = addr[i]; } enable_read_mode(); return(1);}//***************************************************************// Routine:// Description: returns number of sectors if chip supports CFI. // sector_map contains size of each sector.// Returns: false if chip doesn't support CFI.//// WARNING: this only works with flash chips supporting// CFI extended query table 1.1 or greater//***************************************************************int build_sector_map(unsigned int sector_map[], int sector_map_size){ unsigned short array[CFI_END_ADDR]; int ret, i, j; int region_count; int sector_count = 0; int region_sector_count; long region_size; int sector_index = 0; long calculated_flash_size = 0; struct erase_region_info erase_regions[MAX_REGIONS_PER_FLASH]; char major, minor; int ext_table; int bootloc; long flash_id; if ( ! cfi_supported() ) { return 0; } ret = read_cfi_array (array, CFI_END_ADDR + 1); if ( ! ret ) { util_printf("build_sector_map: ERROR unable to read CFI array\n"); return 0; } region_count = array[0x2C]; /* read in the erase region information */ for ( i=0; i<region_count; i++) { erase_regions[i].sectors = (array[0x2E + (i * 4)] << 8) + array[0x2D + (i * 4)] + 1; erase_regions[i].size = ((array[0x30 + (i * 4)] << 8) + array[0x2F + (i * 4)]) * 256; } // // Some chips contain a defect in describing the sector map // The following logic was taked from // linux/drivers/mtd/chips/cfi_cmdset_0002.c start at the line with the // text "Bring me the head of someone at AMD" // ret = read_device_codes(&flash_id); if (!ret) { util_printf(" ERROR: flash chip did not respond to CFI query\n"); return(0); } ext_table = (array[0x16] << 8) + array[0x15]; major = (char) array[ext_table+0x03]; minor = (char) array[ext_table+0x04]; bootloc = array[ext_table+0x0F]; if (((major << 8) | minor) < 0x3131) { /* CFI version 1.0 top / bottom boot not specified, thus building erase sector table not supported */ return(0); } if (bootloc == 3 && region_count > 1) { for (i=0; i<region_count / 2; i++) { j = (region_count-1)-i; region_sector_count = erase_regions[i].sectors; region_size = erase_regions[i].size; erase_regions[i].sectors = erase_regions[j].sectors; erase_regions[i].size = erase_regions[j].size; erase_regions[j].sectors = region_sector_count; erase_regions[j].size = region_size; } } /* process each region in the chip */ for ( i=0; i<region_count; i++) { region_sector_count = erase_regions[i].sectors; sector_count += region_sector_count; region_size = erase_regions[i].size;// util_printf(" Region %d contains %d sectors of size 0x%X\n", // i, region_sector_count, region_size); /*process each sector in the current region */ for (j=0; j<region_sector_count; j++) { if ( sector_index >= sector_map_size) { util_printf( "build_sector_map: ERROR sector map array " "too small %d\n", sector_map_size); return 0; } sector_map[sector_index++] = region_size; calculated_flash_size += region_size; } } if ( (calculated_flash_size >> 20) != (1 << (array[0x27]-20)) ) { util_printf("Warning: calculated flash size doesn't match CFI query " "flash size\n"); util_printf("Calculated flash size: %d Mbytes", calculated_flash_size >> 20); util_printf("CFI stated flash size: %d Mbytes", 1 << (array[0x27]-20)); } return(sector_count);}#endif//***************************************************************// Routine:// Description: returns true if block erased successfully//***************************************************************static int block_erase(volatile unsigned short *block_addr){ volatile unsigned short *addr; int i; //only erase block if it is not already erased if (verify_block_erased((unsigned short *)block_addr, false)) { return(true); } addr = (unsigned short *)BSPCONF_FLASH_BASE; if (FLASH_ID == M29W320DB) { addr[0x555] = 0xAA; addr[0x2AA] = 0x55; addr[0x555] = 0x80; addr[0x555] = 0xAA; addr[0x2AA] = 0x55; *block_addr = 0x30; } else if (FLASH_ID == SST39VF320) { addr[0x5555] = 0xAA; addr[0x2AAA] = 0x55; addr[0x5555] = 0x80; addr[0x5555] = 0xAA; addr[0x2AAA] = 0x55; *block_addr = 0x50; } i = 7; while (*block_addr != 0xFFFF) { io_delay(1000); if (! i--) { return(verify_block_erased((unsigned short *)block_addr, true)); break; } } return(true);}//***************************************************************// Routine:// Description://***************************************************************static int prog_data(volatile unsigned short *block_addr, unsigned short data){ volatile unsigned short *addr; int i, j; if ((*block_addr & data) != data) { // we can only change bits from a "1" to "0". util_printf ("\nProgramming error; flash not erased;"); util_printf (" 0x%X = %x (programming %x)\n", block_addr, *block_addr, data); return -1; } addr = (unsigned short *)BSPCONF_FLASH_BASE; if (FLASH_ID == M29W320DB) { addr[0x555] = 0xAA; addr[0x2AA] = 0x55; addr[0x555] = 0xA0; } else if (FLASH_ID == SST39VF320) { addr[0x5555] = 0xAA; addr[0x2AAA] = 0x55; addr[0x5555] = 0xA0; } *block_addr = data; /* wait a good long time, but not forever */ for (j=0; j < 100 ; j++) { i = 100000; while ( i-- > 0 ) { if (*block_addr == data) { return 0; } } io_delay(100); } return -1;}//***************************************************************// Routine:// Description:// Note: See flash.h for description.//***************************************************************void flash_read(unsigned int offset, // Of flash. unsigned short *dest, // Destination buffer. unsigned int num_bytes, PutValAtAddrCallBack_t CBack){ unsigned int i, num_words; unsigned short fval, *s_addr, *d_addr; s_addr = (unsigned short *)(BSPCONF_FLASH_BASE+offset); d_addr = dest; num_words = ((num_bytes+1)>>1); // round up. for (i=0; i<num_words; i++) { // Flash, for this board, requires that we read words, not bytes. fval = *s_addr; if (CBack) { (*CBack)(d_addr,fval); // write out the the 16bit value. } else { *d_addr=fval; // write out the the 16bit value. } s_addr++; d_addr++; }}//***************************************************************// Routine:// Description:// Note: See flash.h for description.//***************************************************************int flash_write(unsigned int offset, // Of flash. unsigned short *src, // Source buffer. unsigned int num_bytes, GetValAtAddrCallBack_t CBack){ unsigned int i, num_words; unsigned short fval, *d_addr, *s_addr; int ret; s_addr = src; d_addr = (unsigned short *)(BSPCONF_FLASH_BASE+offset); num_words = ((num_bytes+1)>>1); // round up. for (i=0; i<num_words; i++) { if (CBack) { (*CBack)(s_addr,&fval); } else { fval = *s_addr; } ret = prog_data(d_addr,fval); if (ret != 0 ) { return ret; } s_addr++; d_addr++; } return 0;}//***************************************************************// Routine:// Description:// Note: See flash.h for description.//***************************************************************int flash_flush(void){ // Return a -1 if all went well, otherwise // return the flash offset which presented // a problem. return -1;}//***************************************************************// Routine:// Description:// Note: See flash.h for description.//***************************************************************void flash_erase(void){ // Erase the entire flash chip. int i; int err = false; char cmd[10]; for (i=0; i<total_sectors; i++) { util_printf ("Erasing %X to %X\n", sect_info[i].start_addr, sect_info[i].end_addr); err |= !block_erase((unsigned short *)(sect_info[i].start_addr)); } if (err) { util_printf("Press return to continue"); util_gets(cmd, 10); }}//***************************************************************// Routine:// Description:// Note: See flash.h for description.//***************************************************************void flash_erase_range(int start_addr, int end_addr){ int i; int start_erase=-1; int end_erase=-1; util_printf("Erasing blocks containing addresses 0x%X to 0x%X\n", start_addr,end_addr); for (i=0; i<total_sectors; i++) { if ((sect_info[i].start_addr <= start_addr) && (sect_info[i].end_addr >= start_addr)) { start_erase = i; } if ((sect_info[i].start_addr <= end_addr) && (sect_info[i].end_addr >= end_addr)) { end_erase = i; } } if (( start_erase < 0 ) || ( end_erase < 0 )) { util_printf("Erase flash bad address range\n"); } for (i=start_erase; i<=end_erase; i++) { util_printf("Erasing block %i of %i\n",i,total_sectors); block_erase((unsigned short *)(sect_info[i].start_addr)); }}//***************************************************************// Routine:// Description:// Note: See flash.h for description.//***************************************************************int flash_init(){ int i, addr_tally; long flash_id; addr_tally = BSPCONF_FLASH_BASE; i = read_device_codes (&flash_id);/* util_printf ("\n----------------------------------------------------\n"); util_printf (" Flash Device is ... "); if ((i == 1) && (FLASH_ID == M29W320DB)) util_printf (" M29W320DB [ST]\n"); else if ((i == 1) && (FLASH_ID == SST39VF320)) util_printf (" SST39VF320 [SST]\n"); else util_printf ("\n ERROR !!! Unrecognized Flash Device !!! \n"); util_printf ("----------------------------------------------------\n");*/ /* if (i == 1) util_printf ("[Gagamel] Checking ... TRUE [%x]\n", flash_id); else if (i == 0) util_printf ("[Gagamel] Checking ... FALSE\n"); else util_printf ("[Gagamel] Checking ... NOTHING \n");*/#if BSPCONF_FLASH_TYPE == CFI_CMDSET_2 total_sectors = build_sector_map(sect_sizes, TOTAL_SECT); if ( total_sectors == 0 ) { util_printf("\nError: flash chip does not support CFI version 1.1 " "or greater\n"); util_printf("You can not use the CFI CMDSET 2 flash chip driver\n"); util_printf("Select a different flash chip using the BSP configuration " "tool (make bspconfig)\n"); util_printf("Press <Enter>....\n"); util_gets(cmd,CMDMAX); }#else total_sectors = TOTAL_SECT;#endif for ( i = 0 ; i < total_sectors ; i++) { sect_info[i].start_addr = addr_tally; if (FLASH_ID == M29W320DB) addr_tally += M29W320DB_SECT_SIZES[i]; else if (FLASH_ID == SST39VF320) addr_tally += SST39VF320_SECT_SIZES[i]; sect_info[i].end_addr = addr_tally-1; } return 160;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -