📄 flash.c
字号:
flash->mfr = wide_read(flash, ADDR_MANUFACTURER * TYPE_X16 * flash->interleave); /* read device id */ flash->dev_id = wide_read(flash, ADDR_DEVICE_ID * TYPE_X16 * flash->interleave);FDEBUG(safe_printk("mfr: ");)FDEBUG(send_serial_hex(flash->mfr, NL);)FDEBUG(safe_printk("dev_id: ");)FDEBUG(send_serial_hex(flash->dev_id, NL);) if ((flash->interleave == 2) && ((flash->mfr >> 16) == (flash->mfr & 0xffff)) && ((flash->dev_id >> 16) == (flash->dev_id & 0xffff))) { flash->mfr &= 0xffff; flash->dev_id &= 0xffff; } /* reset */ flash_unlock(flash); wide_cmd(flash, CMD_RESET_DATA, ADDR_UNLOCK_1); /* check device type and fill in correct size */ flash->sector_size = 0x10000; switch(flash->dev_id) { case AM29LV160BT: case TC58FVT160: // case MBM29LV160TE: /* This is same id as AM29LV160BT */ message = "16Mb TB"; flash->size = 0x00200000; flash->boot_sector = flash->base + flash->size - flash->sector_size; flash->boot_sector_size[0] = 0x8000; flash->boot_sector_size[1] = 0x2000; flash->boot_sector_size[2] = 0x2000; flash->boot_sector_size[3] = 0x4000; break; // case AM29LV160BB: case TC58FVB160: case MBM29LV160BE: message = "16Mb BB"; flash->size = 0x00200000; flash->boot_sector = flash->base; flash->boot_sector_size[0] = 0x4000; flash->boot_sector_size[1] = 0x2000; flash->boot_sector_size[2] = 0x2000; flash->boot_sector_size[3] = 0x8000; break; case AM29LV800BB: case AM29F800BB: message = "8Mb BB"; flash->size = 0x00100000; flash->boot_sector = flash->base; flash->boot_sector_size[0] = 0x4000; flash->boot_sector_size[1] = 0x2000; flash->boot_sector_size[2] = 0x2000; flash->boot_sector_size[3] = 0x8000; break; case M29W800T: case AM29LV800BT: case AM29F800BT: case TC58FVT800: message = "8Mb TB"; flash->size = 0x00100000; flash->boot_sector = flash->base + flash->size - flash->sector_size; flash->boot_sector_size[0] = 0x8000; flash->boot_sector_size[1] = 0x2000; flash->boot_sector_size[2] = 0x2000; flash->boot_sector_size[3] = 0x4000; break; // case AM29LV800BB: default: if (flash->interleave == 1) { safe_printk( "No single x16 at "); } else { safe_printk( "No interleaved x16 at "); } send_serial_hex((udword)flash->base, NL); return 0; } safe_printk("Found "); if (flash->interleave == 1) { safe_printk("1"); } if (flash->interleave == 2) { flash->size <<= 1; flash->sector_size <<= 1; flash->boot_sector = flash->base + ((flash->boot_sector - flash->base) << 1); flash->boot_sector_size[0] <<= 1; flash->boot_sector_size[1] <<= 1; flash->boot_sector_size[2] <<= 1; flash->boot_sector_size[3] <<= 1; safe_printk("2"); } safe_printk(" x "); safe_printk(message); safe_printk(" at "); send_serial_hex((udword)flash->base, NL); return 1;#endif}/* Intel can erase only one at a time */static intflash_erase(flash_t *flash, unsigned char *ptr, unsigned int size)#ifdef MYINTEL{ unsigned int erased_size = 0; int boot_sector_counter = 0; unsigned char *verify_ptr, *end_ptr; udword cmd,cmd_ul; udword wrstat; int cur_sect_size; unsigned char *block_verify_ptr, *block_end_ptr; end_ptr = ptr + size; for (verify_ptr = ptr; verify_ptr < end_ptr && *verify_ptr == 0xff; verify_ptr++) { /* nothing */; } if (verify_ptr == end_ptr) { safe_printk("No need to erase flash at "); send_serial_hex((udword)ptr, NL); safe_printk("But we will still do it (to unlock all blocks)\r\n"); // return 1; } /* Save ptr for verification below */ verify_ptr = ptr; if (flash->interleave == 2){ cmd = (CMDI_BLOCK_CONFIRM << 16) | CMDI_BLOCK_CONFIRM; cmd_ul = (CMDI_UNLOCK << 16) | CMDI_UNLOCK; } else { cmd = CMDI_BLOCK_CONFIRM; cmd_ul = CMDI_UNLOCK; } safe_printk("Erasing "); send_serial_hex(size, 0); safe_printk(" bytes at "); send_serial_hex((udword)ptr, 0); safe_printk("..."); /* Init erasing of the number of sectors needed. */ /* Intel - Erase one at a time. */ while(erased_size < size) { safe_printk(" bl: "); send_serial_hex((udword)ptr, 0); /* need to unlock block first - all are locked after reset*/ wide_cmd(flash, CMDI_LOCK_CONFIG, 0); if (flash->interleave == 2) { *(udword *)ptr = cmd_ul; } else { *(uword *)ptr = cmd_ul; }// Wait ready (for strataflash?) - actully it unlocks all at once if ((wrstat=wait_flash_ready(flash))) { // could wait forever safe_printk("unlock failed, status: "); send_serial_hex(wrstat, NL); return 0; // erase failed } /* now try erase it */ /* we'll see if needed */ if (ptr < flash->boot_sector || ptr >= (flash->boot_sector + flash->sector_size)) { cur_sect_size= flash->sector_size; } else { cur_sect_size=flash->boot_sector_size[boot_sector_counter++]; } /* switch to read array mode */ wide_cmd(flash, CMDI_READ_ARRAY, 0); block_end_ptr=ptr+cur_sect_size; for (block_verify_ptr = ptr; (block_verify_ptr < block_end_ptr) && *block_verify_ptr == 0xff; block_verify_ptr++) {; // nothing } if (block_verify_ptr < block_end_ptr) { wide_cmd(flash, CMDI_BLOCK_ERASE, 0); if (flash->interleave == 2) { *(udword *)ptr = cmd; } else { *(uword *)ptr = cmd; } if ((wrstat=wait_flash_ready(flash))) { // could wait forever safe_printk("erase failed, status: "); send_serial_hex(wrstat, NL); return 0; // erase failed } } erased_size += cur_sect_size; ptr += cur_sect_size; } /* switch to read array mode */ wide_cmd(flash, CMDI_READ_ARRAY, 0); safe_printk("done, verifying..."); for (; verify_ptr < end_ptr && *verify_ptr == 0xff; verify_ptr++) { /* nothing */; } if (verify_ptr != end_ptr) { safe_printk("error at "); send_serial_hex((udword)verify_ptr, NL); return 0; } safe_printk("OK\n"); return 1;}#else{ unsigned int erased_size = 0; int boot_sector_counter = 0; unsigned char *verify_ptr, *end_ptr; udword cmd; end_ptr = ptr + size; for (verify_ptr = ptr; verify_ptr < end_ptr && *verify_ptr == 0xff; verify_ptr++) { /* nothing */; } if (verify_ptr == end_ptr) { /* No need to erase */ return 1; } /* Save ptr for verification below */ verify_ptr = ptr; if (flash->interleave == 2) { cmd = (CMD_SECTOR_ERASE_UNLOCK_DATA_2 << 16) | CMD_SECTOR_ERASE_UNLOCK_DATA_2; } else { cmd = CMD_SECTOR_ERASE_UNLOCK_DATA_2; } send_serial_hex((udword)ptr, 0); safe_printk(": Erasing "); send_serial_hex(size, 0); safe_printk(" bytes..."); /* Init erasing of the number of sectors needed. */ flash_unlock(flash); wide_cmd(flash, CMD_SECTOR_ERASE_UNLOCK_DATA_1, ADDR_UNLOCK_1); flash_unlock(flash); while(erased_size < size) { if (flash->interleave == 2) { *(udword *)ptr = cmd; } else { *(uword *)ptr = cmd; } if (ptr < flash->boot_sector || ptr >= (flash->boot_sector + flash->sector_size)) { erased_size += flash->sector_size; ptr += flash->sector_size; } else { erased_size += flash->boot_sector_size[boot_sector_counter]; ptr += flash->boot_sector_size[boot_sector_counter++]; } } /* give time for busy signal to be ready */ nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); while(flash_is_busy(flash, 0)) /* nothing */; safe_printk("done, verifying..."); for (; verify_ptr < end_ptr && *verify_ptr == 0xff; verify_ptr++) { /* nothing */; } if (verify_ptr != end_ptr) { safe_printk("error at "); send_serial_hex((udword)verify_ptr, NL); return 0; } safe_printk("OK\n"); return 1;}#endifintflash_write_part(flash_t *flash, const unsigned char *source, unsigned int offset, unsigned int size){#ifdef MYINTEL int i; udword data32;#endif int chunk_size;// char retry_number[2] = ""; unsigned int end_offset = offset + size; udword wrstat; /* do the writing */ send_serial_hex((udword) (flash->base + offset), 0); safe_printk(": Writing "); send_serial_hex(size, 0); safe_printk(" bytes...");#ifdef MYINTEL/* Write buffer support */ if ((flash->buffer_size) && (((end_offset-offset)>>((flash->buswidth>2)?2:1)) >= flash->buffer_size)) { safe_printk("BW");// Wait buffer ready while (((end_offset-offset)>>((flash->buswidth>2)?2:1)) >= flash->buffer_size) {// send_serial_hex(offset, 0); if (flash->interleave == 2) do { wide_cmd(flash, CMDI_WRITE_BUFFER, offset); //next read will be XSRB } while ((~(data32=wide_read(flash, offset))) & ((INTEL_XSRB_WBS) | (INTEL_XSRB_WBS << 16))); else do { wide_cmd(flash, CMDI_WRITE_BUFFER, offset); } while ((~(data32=wide_read(flash, offset))) & INTEL_XSRB_WBS); wide_cmd(flash, (flash->buffer_size)-1, offset); for (i=0;i<(flash->buffer_size);i++) { chunk_size = wide_write_chunk(flash, offset, source); offset += chunk_size; source += chunk_size; } wide_cmd(flash, CMDI_WRITE_BUFFER_CONFIRM, offset); } // while (((end_offset-offset)>>((flash->buswidth>2)?2:1)) >= flash->buffer_size) if ((wrstat=wait_flash_ready(flash))) { // could wait forever safe_printk("write failed, status: "); send_serial_hex(wrstat, NL); return 0; // write failed }/* switch to read array mode */ wide_cmd(flash, CMDI_READ_ARRAY, 0); }#endif while (offset < end_offset) { int retries = 0; do {#ifdef MYINTEL wide_cmd(flash, CMDI_PROGRAM, 0); chunk_size = wide_write_chunk(flash, offset, source); if ((wrstat=wait_flash_ready(flash))) { // could wait forever safe_printk("write failed, status: "); send_serial_hex(wrstat, NL); return 0; // write failed } /* switch to read array mode */ wide_cmd(flash, CMDI_READ_ARRAY, 0);#else int timeout; flash_unlock(flash); wide_cmd(flash, CMD_PROGRAM_UNLOCK_DATA, ADDR_UNLOCK_1); chunk_size = wide_write_chunk(flash, offset, source); /* give time for busy signal to be ready */ nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); /* Wait for programming to finish. */ timeout = 500000; while(timeout-- && flash_is_busy(flash, offset)) { /* nothing */; } if (!timeout) { safe_printk("Timed out!\n"); }#endif if ((flash->interleave == 1) && (wide_read(flash, offset) == *((uword *)source))) { break; } if ((flash->interleave == 2) && (wide_read(flash, offset) == *((udword *)source))) { break; } if (++retries < 10) { safe_printk("Verify error at "); send_serial_hex((udword)flash->base + offset, NL); } } while (retries < 10); if (retries >= 10) { safe_printk("Fatal verify error.\n"); return 0; } offset += chunk_size; source += chunk_size; } safe_printk("verified\n"); return 1;}#ifdef MYINTELintflash_verify_part(flash_t *flash, const unsigned char *source, unsigned int offset, unsigned int size){ unsigned int end_offset = offset + size; int match=1; /* do the comparing */ send_serial_hex((udword) (flash->base + offset), 0); safe_printk(": Verifying "); send_serial_hex(size, 0); safe_printk(" bytes..."); /* switch to read array mode */ wide_cmd(flash, CMDI_READ_ARRAY, 0); while (offset < end_offset) { if (((flash->interleave == 1) && (wide_read(flash, offset) != *((uword *)source))) | ((flash->interleave == 2) && (wide_read(flash, offset) != *((udword *)source)))) {// safe_printk("Mismatch at "); send_serial_hex((udword)flash->base + offset, 0); safe_printk(" read:"); send_serial_hex(wide_read(flash, offset),0); safe_printk(" expected:"); send_serial_hex( *((uword *)source) ,0); safe_printk("\n"); match=0; } offset += (flash->buswidth); source += (flash->buswidth); } if (match) safe_printk("match\n"); return match;}#else#endifvoidflash_write(const unsigned char *source, unsigned int offset, unsigned int size){ int flashes_found = 0; unsigned int total_flash_size = 0; int i = 0; int verify_only=0; if (size & 0x80000000) { size&=0x7fffffff; verify_only=1; } while (flashes_found < sizeof flashes / sizeof flashes[0]) { flashes[flashes_found].type = TYPE_X16; flashes[flashes_found].interleave = 1; flashes[flashes_found].buswidth = 2; if (!flash_probe(&flashes[flashes_found])) { flashes[flashes_found].interleave = 2; flashes[flashes_found].buswidth = 4; if (!flash_probe(&flashes[flashes_found])) { break; } } total_flash_size += flashes[flashes_found].size; flashes_found++; } if (offset + size > total_flash_size) { safe_printk("flash too small\n"); return; } /* erase and write */ for (; i < flashes_found && size; i++) { if (offset < flashes[i].size) { unsigned int cur_size; if (offset + size > flashes[i].size) cur_size = flashes[i].size - offset; else cur_size = size; if (!verify_only) { if (!flash_erase(&flashes[i], (unsigned char *)flashes[i].base + offset, cur_size)) { return; } if (!flash_write_part(&flashes[i], source, offset, cur_size)) { return; } }#ifdef MYINTEL// for now verify chip-by-chip - better verify all later if (!flash_verify_part(&flashes[i], source, offset, cur_size)) { return; }#endif offset = 0; size -= cur_size; source += cur_size; } else { offset -= flashes[i].size; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -