#include /*----------------------------------------------------------------------- * read jedec ids from device and set corresponding fields in info struct * * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct * */ static void intel_read_jedec_ids (flash_info_t * info) { info->manufacturer_id = 0; info->device_id = 0; info->device_id2 = 0; flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID); udelay(1000); /* some flash are slow to respond */ info->manufacturer_id = flash_read_uchar (info, FLASH_OFFSET_MANUFACTURER_ID); info->device_id = flash_read_uchar (info, FLASH_OFFSET_DEVICE_ID); flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); } /*----------------------------------------------------------------------- * 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, uint64_t tout, char *prompt) { int retcode; retcode = flash_status_check (info, sector, tout, prompt); 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); return retcode; } /* * 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 intel_flash_is_busy (flash_info_t * info, flash_sect_t sect) { return !flash_isset (info, sect, 0, FLASH_STATUS_DONE); } static int intel_flash_erase_one (flash_info_t * info, long sect) { int rcode = 0; flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS); flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE); flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM); if (flash_full_status_check (info, sect, info->erase_blk_tout, "erase")) { rcode = 1; } else putc ('.'); return rcode; } static void intel_flash_prepare_write(flash_info_t * info) { flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS); flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE); } #ifdef CONFIG_CFI_BUFFER_WRITE static int intel_flash_write_cfibuffer (flash_info_t * info, ulong dest, const uchar * cp, int len) { flash_sect_t sector; int cnt; int retcode; volatile cfiptr_t src; volatile cfiptr_t dst; src.cp = (uchar *)cp; dst.cp = (uchar *) dest; sector = find_sector (info, dest); flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); if ((retcode = flash_status_check (info, sector, info->buffer_write_tout, "write to buffer")) == ERR_OK) { /* reduce the number of loops by the width of the port */ switch (info->portwidth) { case FLASH_CFI_8BIT: cnt = len; break; case FLASH_CFI_16BIT: cnt = len >> 1; break; case FLASH_CFI_32BIT: cnt = len >> 2; break; case FLASH_CFI_64BIT: cnt = len >> 3; break; default: return ERR_INVAL; break; } flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) { switch (info->portwidth) { case FLASH_CFI_8BIT: *dst.cp++ = *src.cp++; break; case FLASH_CFI_16BIT: *dst.wp++ = *src.wp++; break; case FLASH_CFI_32BIT: *dst.lp++ = *src.lp++; break; case FLASH_CFI_64BIT: *dst.llp++ = *src.llp++; break; default: return ERR_INVAL; break; } } flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM); retcode = flash_full_status_check (info, sector, info->buffer_write_tout, "buffer write"); } return retcode; } #endif /* CONFIG_CFI_BUFFER_WRITE */ struct cfi_cmd_set cfi_cmd_set_intel = { .flash_write_cfibuffer = intel_flash_write_cfibuffer, .flash_erase_one = intel_flash_erase_one, .flash_is_busy = intel_flash_is_busy, .flash_read_jedec_ids = intel_read_jedec_ids, .flash_prepare_write = intel_flash_prepare_write, };