📄 cfi_flash.c
字号:
break; case FLASH_CFI_32BIT: debug ("is= %8.8x %8.8lx\n", flash_read32(addr), cword.l); retval = (flash_read32(addr) == cword.l); break; case FLASH_CFI_64BIT:#ifdef DEBUG { char str1[20]; char str2[20]; print_longlong (str1, flash_read64(addr)); print_longlong (str2, cword.ll); debug ("is= %s %s\n", str1, str2); }#endif retval = (flash_read64(addr) == cword.ll); break; default: retval = 0; break; } flash_unmap(info, sect, offset, addr); return retval;}/*----------------------------------------------------------------------- */static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd){ void *addr; cfiword_t cword; int retval; addr = flash_map (info, sect, offset); flash_make_cmd (info, cmd, &cword); switch (info->portwidth) { case FLASH_CFI_8BIT: retval = ((flash_read8(addr) & cword.c) == cword.c); break; case FLASH_CFI_16BIT: retval = ((flash_read16(addr) & cword.w) == cword.w); break; case FLASH_CFI_32BIT: retval = ((flash_read32(addr) & cword.l) == cword.l); break; case FLASH_CFI_64BIT: retval = ((flash_read64(addr) & cword.ll) == cword.ll); break; default: retval = 0; break; } flash_unmap(info, sect, offset, addr); return retval;}/*----------------------------------------------------------------------- */static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd){ void *addr; cfiword_t cword; int retval; addr = flash_map (info, sect, offset); flash_make_cmd (info, cmd, &cword); switch (info->portwidth) { case FLASH_CFI_8BIT: retval = flash_read8(addr) != flash_read8(addr); break; case FLASH_CFI_16BIT: retval = flash_read16(addr) != flash_read16(addr); break; case FLASH_CFI_32BIT: retval = flash_read32(addr) != flash_read32(addr); break; case FLASH_CFI_64BIT: retval = flash_read64(addr) != flash_read64(addr); break; default: retval = 0; break; } flash_unmap(info, sect, offset, addr); return retval;}/* * flash_is_busy - check to see if the flash is busy * * This routine checks the status of the chip and returns true if the * chip is busy. */static int flash_is_busy (flash_info_t * info, flash_sect_t sect){ int retval; switch (info->vendor) { case CFI_CMDSET_INTEL_PROG_REGIONS: case CFI_CMDSET_INTEL_STANDARD: case CFI_CMDSET_INTEL_EXTENDED: retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE); break; case CFI_CMDSET_AMD_STANDARD: case CFI_CMDSET_AMD_EXTENDED:#ifdef CONFIG_FLASH_CFI_LEGACY case CFI_CMDSET_AMD_LEGACY:#endif retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE); break; default: retval = 0; } debug ("flash_is_busy: %d\n", retval); return retval;}/*----------------------------------------------------------------------- * wait for XSR.7 to be set. Time out with an error if it does not. * This routine does not set the flash to read-array mode. */static int flash_status_check (flash_info_t * info, flash_sect_t sector, ulong tout, char *prompt){ ulong start;#if CFG_HZ != 1000 tout *= CFG_HZ/1000;#endif /* Wait for command completion */ start = get_timer (0); while (flash_is_busy (info, sector)) { if (get_timer (start) > tout) { printf ("Flash %s timeout at address %lx data %lx\n", prompt, info->start[sector], flash_read_long (info, sector, 0)); flash_write_cmd (info, sector, 0, info->cmd_reset); return ERR_TIMOUT; } udelay (1); /* also triggers watchdog */ } return ERR_OK;}/*----------------------------------------------------------------------- * Wait for XSR.7 to be set, if it times out print an error, otherwise * do a full status check. * * This routine sets the flash to read-array mode. */static int flash_full_status_check (flash_info_t * info, flash_sect_t sector, ulong tout, char *prompt){ int retcode; retcode = flash_status_check (info, sector, tout, prompt); switch (info->vendor) { case CFI_CMDSET_INTEL_PROG_REGIONS: case CFI_CMDSET_INTEL_EXTENDED: case CFI_CMDSET_INTEL_STANDARD: if ((retcode != ERR_OK) && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) { retcode = ERR_INVAL; printf ("Flash %s error at address %lx\n", prompt, info->start[sector]); if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) { puts ("Command Sequence Error.\n"); } else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) { puts ("Block Erase Error.\n"); retcode = ERR_NOT_ERASED; } else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) { puts ("Locking Error\n"); } if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) { puts ("Block locked.\n"); retcode = ERR_PROTECTED; } if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS)) puts ("Vpp Low Error.\n"); } flash_write_cmd (info, sector, 0, info->cmd_reset); break; default: break; } return retcode;}/*----------------------------------------------------------------------- */static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c){#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) unsigned short w; unsigned int l; unsigned long long ll;#endif switch (info->portwidth) { case FLASH_CFI_8BIT: cword->c = c; break; case FLASH_CFI_16BIT:#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) w = c; w <<= 8; cword->w = (cword->w >> 8) | w;#else cword->w = (cword->w << 8) | c;#endif break; case FLASH_CFI_32BIT:#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) l = c; l <<= 24; cword->l = (cword->l >> 8) | l;#else cword->l = (cword->l << 8) | c;#endif break; case FLASH_CFI_64BIT:#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) ll = c; ll <<= 56; cword->ll = (cword->ll >> 8) | ll;#else cword->ll = (cword->ll << 8) | c;#endif break; }}/* loop through the sectors from the highest address when the passed * address is greater or equal to the sector address we have a match */static flash_sect_t find_sector (flash_info_t * info, ulong addr){ flash_sect_t sector; for (sector = info->sector_count - 1; sector >= 0; sector--) { if (addr >= info->start[sector]) break; } return sector;}/*----------------------------------------------------------------------- */static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword){ void *dstaddr; int flag; flash_sect_t sect; dstaddr = map_physmem(dest, info->portwidth, MAP_NOCACHE); /* Check if Flash is (sufficiently) erased */ switch (info->portwidth) { case FLASH_CFI_8BIT: flag = ((flash_read8(dstaddr) & cword.c) == cword.c); break; case FLASH_CFI_16BIT: flag = ((flash_read16(dstaddr) & cword.w) == cword.w); break; case FLASH_CFI_32BIT: flag = ((flash_read32(dstaddr) & cword.l) == cword.l); break; case FLASH_CFI_64BIT: flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll); break; default: flag = 0; break; } if (!flag) { unmap_physmem(dstaddr, info->portwidth); return ERR_NOT_ERASED; } /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts (); switch (info->vendor) { case CFI_CMDSET_INTEL_PROG_REGIONS: case CFI_CMDSET_INTEL_EXTENDED: case CFI_CMDSET_INTEL_STANDARD: flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS); flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE); break; case CFI_CMDSET_AMD_EXTENDED: case CFI_CMDSET_AMD_STANDARD:#ifdef CONFIG_FLASH_CFI_LEGACY case CFI_CMDSET_AMD_LEGACY:#endif sect = find_sector(info, dest); flash_unlock_seq (info, sect); flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_WRITE); break; } switch (info->portwidth) { case FLASH_CFI_8BIT: flash_write8(cword.c, dstaddr); break; case FLASH_CFI_16BIT: flash_write16(cword.w, dstaddr); break; case FLASH_CFI_32BIT: flash_write32(cword.l, dstaddr); break; case FLASH_CFI_64BIT: flash_write64(cword.ll, dstaddr); break; } /* re-enable interrupts if necessary */ if (flag) enable_interrupts (); unmap_physmem(dstaddr, info->portwidth); return flash_full_status_check (info, find_sector (info, dest), info->write_tout, "write");}#ifdef CFG_FLASH_USE_BUFFER_WRITEstatic int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len){ flash_sect_t sector; int cnt; int retcode; void *src = cp; void *dst = map_physmem(dest, len, MAP_NOCACHE); void *dst2 = dst; int flag = 0; uint offset = 0; unsigned int shift; uchar write_cmd; switch (info->portwidth) { case FLASH_CFI_8BIT: shift = 0; break; case FLASH_CFI_16BIT: shift = 1; break; case FLASH_CFI_32BIT: shift = 2; break; case FLASH_CFI_64BIT: shift = 3; break; default: retcode = ERR_INVAL; goto out_unmap; } cnt = len >> shift; while ((cnt-- > 0) && (flag == 0)) { switch (info->portwidth) { case FLASH_CFI_8BIT: flag = ((flash_read8(dst2) & flash_read8(src)) == flash_read8(src)); src += 1, dst2 += 1; break; case FLASH_CFI_16BIT: flag = ((flash_read16(dst2) & flash_read16(src)) == flash_read16(src)); src += 2, dst2 += 2; break; case FLASH_CFI_32BIT: flag = ((flash_read32(dst2) & flash_read32(src)) == flash_read32(src)); src += 4, dst2 += 4; break; case FLASH_CFI_64BIT: flag = ((flash_read64(dst2) & flash_read64(src)) == flash_read64(src)); src += 8, dst2 += 8; break; } } if (!flag) { retcode = ERR_NOT_ERASED; goto out_unmap; } src = cp; sector = find_sector (info, dest); switch (info->vendor) { case CFI_CMDSET_INTEL_PROG_REGIONS: case CFI_CMDSET_INTEL_STANDARD: case CFI_CMDSET_INTEL_EXTENDED: write_cmd = (info->vendor == CFI_CMDSET_INTEL_PROG_REGIONS) ? FLASH_CMD_WRITE_BUFFER_PROG : FLASH_CMD_WRITE_TO_BUFFER; flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); flash_write_cmd (info, sector, 0, FLASH_CMD_READ_STATUS); flash_write_cmd (info, sector, 0, write_cmd); retcode = flash_status_check (info, sector, info->buffer_write_tout, "write to buffer"); if (retcode == ERR_OK) { /* reduce the number of loops by the width of * the port */ cnt = len >> shift; flash_write_cmd (info, sector, 0, cnt - 1); while (cnt-- > 0) { switch (info->portwidth) { case FLASH_CFI_8BIT: flash_write8(flash_read8(src), dst); src += 1, dst += 1; break; case FLASH_CFI_16BIT: flash_write16(flash_read16(src), dst); src += 2, dst += 2; break; case FLASH_CFI_32BIT: flash_write32(flash_read32(src), dst); src += 4, dst += 4; break; case FLASH_CFI_64BIT: flash_write64(flash_read64(src), dst); src += 8, dst += 8; break; default: retcode = ERR_INVAL; goto out_unmap; } } flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM); retcode = flash_full_status_check ( info, sector, info->buffer_write_tout, "buffer write"); } break; case CFI_CMDSET_AMD_STANDARD: case CFI_CMDSET_AMD_EXTENDED: flash_unlock_seq(info,0);#ifdef CONFIG_FLASH_SPANSION_S29WS_N offset = ((unsigned long)dst - info->start[sector]) >> shift;#endif flash_write_cmd(info, sector, offset, AMD_CMD_WRITE_TO_BUFFER); cnt = len >> shift; flash_write_cmd(info, sector, offset, (uchar)cnt - 1); switch (info->portwidth) { case FLASH_CFI_8BIT: while (cnt-- > 0) { flash_write8(flash_read8(src), dst); src += 1, dst += 1; } break; case FLASH_CFI_16BIT: while (cnt-- > 0) { flash_write16(flash_read16(src), dst); src += 2, dst += 2; } break; case FLASH_CFI_32BIT: while (cnt-- > 0) { flash_write32(flash_read32(src), dst); src += 4, dst += 4; } break; case FLASH_CFI_64BIT: while (cnt-- > 0) { flash_write64(flash_read64(src), dst); src += 8, dst += 8; } break; default: retcode = ERR_INVAL; goto out_unmap; } flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM); retcode = flash_full_status_check (info, sector, info->buffer_write_tout, "buffer write"); break; default: debug ("Unknown Command Set\n"); retcode = ERR_INVAL; break; }out_unmap: unmap_physmem(dst, len); return retcode;}#endif /* CFG_FLASH_USE_BUFFER_WRITE *//*----------------------------------------------------------------------- */int flash_erase (flash_info_t * info, int s_first, int s_last)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -