📄 flash_v3.c
字号:
if( ret == 1 ) { if( (dq1 & status) == dq1 ) { uart_printf( "Flash write to Buffer aborted @ 0x%lx = 0x%x\n", adr, status ); cfi_send_cmd(0xAA, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0xF0, pcfi->addr_unlock1, pcfi->base); } else { uart_printf( "Flash write to buffer faileed @ 0x%lx = 0x%x\n", adr, status ); cfi_send_gen_cmd(0xF0, 0, pcfi->base); } } return ret;//zxh- }int flash_write_data_internal(unsigned long addr, unsigned short *data, int nwords, cfi_info_t *pcfi){ int i; int chipnum; int len = nwords << 1; int ret = 0; int wbufsize = CFIDEV_INTERLEAVE << 5; //cfi->cfiq->MaxBufWriteSize=0x5 unsigned long ofs; unsigned char *buf = (unsigned char*)data; #ifndef FLASH_USE_DQX int cnt = 0;#endif #if (CFIDEV_BUSWIDTH != 1 && CFIDEV_BUSWIDTH != 2)#error "Current code doesn't support other than 8-bits and 16-bits writing"#endif #ifdef CFIDEV_UNLOCK_BYPASS cfi_send_cmd(0xaa, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0x20, pcfi->addr_unlock1, pcfi->base);#endif#if CFIDEV_BUSWIDTH == 1#if 0 for (i = 0; i < (nwords << 1); ++i) {#ifdef CFIDEV_UNLOCK_BYPASS cfi_send_cmd(0xa0, 0x111, pcfi->base);// uart_puts("bypass mode\n");#else cfi_send_cmd(0xaa, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0xa0, pcfi->addr_unlock1, pcfi->base);#endif cfi_write(((unsigned char *) data)[i], addr + i);#ifdef FLASH_USE_DQX dqx_wait(addr + i, ((unsigned char *)data)[i], 1<<pcfi->ident.timeout_single_write);#else for (cnt = 0; cnt < FLASH_ERR_CNT; cnt++) { em86xx_usleep(1 << pcfi->ident.timeout_single_write); if (cfi_read(addr + i) == ((unsigned char *)data)[i]) break; }#endif }#else //Buffer write method. /* Write buffer is worth it only if more than one word to write... */ //zxh:Why 0x23? I don't know. chipnum = addr >> 0x23; //cfi->chipshift=0x17 (0x800000 8MB) ofs = addr - (chipnum << 0x23); while(len > CFIDEV_BUSWIDTH) { /* We must not cross write block boundaries */ int size = wbufsize - (ofs & (wbufsize-1)); if (size > len) size = len & ~(CFIDEV_BUSWIDTH-1); ret = do_write_buffer(pcfi, ofs, buf, size); if (ret) return ret; ofs += size; buf += size; len -= size; }#endif#elif CFIDEV_BUSWIDTH == 2 for (i = 0; i < nwords; ++i) {#ifdef CFIDEV_UNLOCK_BYPASS cfi_send_cmd(0xa0, 0, pcfi->base);// uart_puts("bypass mode**************aaaaaaaaaaaaaaa");#else cfi_send_cmd(0xaa, 0, pcfi->base); cfi_send_cmd(0x55, 0, pcfi->base); cfi_send_cmd(0xa0, 0, pcfi->base);#endif cfi_write(data[i], addr + (i << 1));#ifdef FLASH_USE_DQX dqx_wait(addr + (i << 1), data[i], 1<<pcfi->ident.timeout_single_write);#else for (cnt = 0; cnt < FLASH_ERR_CNT; cnt++) { em86xx_usleep(1 << pcfi->ident.timeout_single_write); if (cfi_read(addr + (i << 1)) == data[i]) break; }#endif }#endif#ifdef CFIDEV_UNLOCK_BYPASS cfi_send_cmd(0x90, 0, pcfi->base); cfi_send_cmd(0x00, 0, pcfi->base);#endif return FLASH_OK;}#define PROGRESS_UNIT 0x1000 // prints '.' after this block is written #define UNLOCKBYPASSPROGRAM_UNITBITS 12 // 2^12 = 4KBint flash_write_data(unsigned long addr, unsigned char *data, int len){ int cnt = 0; int times, p1, p2, t1, t2; //Kenlo int maxbufwords, nwords; cfi_info_t *pcfi = find_cfi(addr); int nloop = 0, writtenlen = 0, nextwrittenlen = PROGRESS_UNIT;#if (CFIDEV_BUSWIDTH != 1 && CFIDEV_BUSWIDTH != 2)#error "Current code doesn't support other than 8-bits and 16-bits writing"#endif if (pcfi == NULL) return FLASH_NOTEXIST; if (pcfi->chip_state != FLSTATE_READY) return FLASH_NOTREADY; if (!flash_writable(addr, len)) return FLASH_WRITE_FAULT; if (addr & 0x01) { flash_write_onebyte(addr++, *data++); --len; } pcfi->chip_state = FLSTATE_WRITING; if (pcfi->ident.max_multibyte_write == 0) maxbufwords = 1 << (UNLOCKBYPASSPROGRAM_UNITBITS - 1); else maxbufwords = 1 << (pcfi->ident.max_multibyte_write - 1); while (len > 1) { if (writtenlen >= nextwrittenlen) { if ((++nloop & 0x3f) == 0) uart_puts("\r\n "); uart_putc('.'); nextwrittenlen += PROGRESS_UNIT; } nwords = ((len + 1) >> 1); if (nwords > maxbufwords) nwords = maxbufwords; flash_write_data_internal(addr, (unsigned short *) data, nwords, pcfi); for (cnt = 0; cnt < FLASH_ERR_CNT; cnt++) { em86xx_usleep(1 << pcfi->ident.timeout_single_write);#if CFIDEV_BUSWIDTH == 1 if (cfi_read(addr) == *(unsigned char *) data) break;#elif CFIDEV_BUSWIDTH == 2 if (cfi_read(addr) == *(unsigned short *) data) break;#endif } if (cnt >= FLASH_ERR_CNT) break; nwords <<= 1; writtenlen += nwords; addr += nwords; data += nwords; len -= nwords; } pcfi->chip_state = FLSTATE_READY; if (cnt >= FLASH_ERR_CNT) return FLASH_WRITE_FAULT; if (len == 1) flash_write_onebyte(addr, *data); return FLASH_OK;}//// miscellaneous//char *cfi_get_idname(unsigned int vendor){ switch (vendor) { case CFI_PRIMARY_ID_NULL : return "None"; case CFI_PRIMARY_ID_INTEL_EXT : return "Intel/Sharp Extended"; case CFI_PRIMARY_ID_AMD_STD : return "AMD/Fujitsu Standard"; case CFI_PRIMARY_ID_INTEL_STD : return "Intel/Sharp Standard"; case CFI_PRIMARY_ID_AMD_EXT : return "AMD/Fujitsu Extended"; case CFI_PRIMARY_ID_MITSUBISHI_STD : return "Mitsubishi Standard"; case CFI_PRIMARY_ID_MITSUBISHI_EXT : return "Mitsubishi Extended"; case CFI_PRIMARY_ID_SST : return "Page Write Command Set"; case CFI_PRIMARY_ID_RESERVED : return "Not Allowed / Reserved for Future Use"; default: return "Unknown"; }}void flash_list(void *vpcfi){ int i, j; cfi_info_t *pcfi; for (i = 0; i < FLASH_MAX_CHIPSET; ++i) { pcfi = &g_cfi[i]; if (pcfi->exist && (vpcfi == NULL || i == (int) vpcfi || pcfi == vpcfi)) { uart_printf("Flash %d at 0x%08x\n", i, pcfi->base); uart_printf(" ID : %s\n", cfi_get_idname(pcfi->ident.primary_id)); uart_printf(" Size : %d KB\n", pcfi->size >> 10); uart_printf(" Buffer Size : %d\n", pcfi->ident.max_multibyte_write); uart_printf(" Regions : %d\n", pcfi->ident.num_erase_regions); for (j = 0; j < pcfi->ident.num_erase_regions; ++j) uart_printf(" %d : 0x%08x - 0x%08x * %2d\n", j, pcfi->erase_regions[j].start, pcfi->erase_regions[j].size, pcfi->erase_regions[j].blocks); } }}int flash_calcblock(unsigned long addr, unsigned int *pstart, unsigned int *plen){ int i; cfi_info_t *pcfi = find_cfi(addr); *pstart = 0; *plen = 0; if (pcfi == NULL) return -1; for (i = pcfi->ident.num_erase_regions - 1; i >= 0; --i) { if (addr >= pcfi->base + pcfi->erase_regions[i].start) { *pstart = pcfi->base + pcfi->erase_regions[i].start; *plen = pcfi->erase_regions[i].size; addr -= *pstart; while (addr >= *plen) { addr -= *plen; *pstart += *plen; } return 0; } } return -1;}//// Test// #define FLEX_ROM_SIZE 0x00200000 // 2MB#define FLEX_BLOCK_SIZE 0x100 // 256 bytes#define CALC_SEED(addr) ((unsigned char) (((((addr) >> 8) & 0xff) + 3) * 5 + ((((addr) >> 16) & 0xff) + 5) * 7))#define CALC_SEED_NEXT(seed) (++(seed))#define MISMATCH_THRESHOLD 10#ifdef CONFIG_ENABLE_FULLFUNCTIONvoid flash_test_flexrom(void){ int i, j, mismatch, bit, bitmask; unsigned long addr, flexaddr = LOADER_FLASHBASE; unsigned char seed, seedtable[FLEX_BLOCK_SIZE]; uart_puts("FlexROM Test :\n"); for (i = 0, addr = 0, mismatch = 0; i < FLEX_ROM_SIZE / FLEX_BLOCK_SIZE; ++i, addr += FLEX_BLOCK_SIZE, flexaddr += FLEX_BLOCK_SIZE) { seed = CALC_SEED(addr); for (j = 0; j < FLEX_BLOCK_SIZE; ++j, CALC_SEED_NEXT(seed)) seedtable[j] = seed; for (j = 0; j < FLEX_BLOCK_SIZE; ++j) { if (__raw_readb(flexaddr + j) != seedtable[j]) { if (mismatch == 0) { if (addr == 0) bit = 0; else for (bit = 0, bitmask = 1; (addr & bitmask) == 0; ++bit, bitmask <<= 1) ; uart_printf(" Guess address line %d is wrong\n", bit); } uart_printf(" Data Mismatch at %08lx : %02x (orig = %02x)\n", flexaddr + j, __raw_readb(flexaddr + j), seedtable[j]); if (++mismatch >= MISMATCH_THRESHOLD) { uart_puts(" Too many mismatches!\n"); return; } } } } if (mismatch == 0) uart_puts(" OK\n"); else uart_printf(" Mismatch = %d\n", mismatch);}void flash_test_checksum(void){ int i; unsigned int *ptr, sum; for (i = 0; i < FLASH_MAX_CHIPSET; ++i) { if (g_cfi[i].exist) { uart_printf(finfo_msg, i, g_cfi[i].base, g_cfi[i].size); for (sum = 0, ptr = (unsigned int *) g_cfi[i].base; ptr < (unsigned int *) (g_cfi[i].base + g_cfi[i].size); ++ptr) sum += *ptr; uart_printf(" Checksum = %08x\n", sum); } }}void flash_test_write(void){ unsigned int len; unsigned char buf[256], emptybuf[256]; int i, j, found, testlen = sizeof emptybuf; uart_puts("Write test :\n"); if (len > sizeof buf) len = sizeof buf; for (i = 0; i < FLASH_MAX_CHIPSET; ++i) { if (g_cfi[i].exist) { uart_printf(finfo_msg, i, g_cfi[i].base, g_cfi[i].size); memset(emptybuf, 0xff, sizeof emptybuf); for (len = g_cfi[i].size, found = 0; len > testlen; len -= testlen) { flash_read_data(g_cfi[i].base + len, buf, testlen); if (memcmp(buf, emptybuf, testlen) == 0) { found = 1; break; } } if (!found) { uart_puts(" No empty block found. Test failed\n"); return; } uart_printf(" Empty block is found at offset %04x\n", len); uart_puts(" Writing...\n"); for (j = 0; j < testlen; ++j) emptybuf[j] = j; flash_write_data(g_cfi[i].base + len, emptybuf, testlen); uart_puts(" Reading...\n"); flash_read_data(g_cfi[i].base + len, buf, testlen); uart_puts(" Verifying : "); if (memcmp(buf, emptybuf, testlen) == 0) uart_puts("OK\n"); else uart_puts("Mismatch\n"); } }} void flash_test(int argc, char *argv[]){ int doall = (argv[0] && strcmp(argv[0], "all") == 0) ? 1 : 0; if (argv[0] == NULL) { uart_puts("Parallel Flash Test :\n"); uart_puts(" Available commands : " "flexrom " "checksum " "write " "\n"); } else { if (strcmp(argv[0], "flexrom") == 0) { flash_test_flexrom(); } if (!flash_found()) { uart_puts("Parallel Flash doesn't exist. Test failed\n"); return; } if (doall || strcmp(argv[0], "checksum") == 0) { flash_test_checksum(); } if (doall || strcmp(argv[0], "write") == 0) { flash_test_write(); } }}#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -