#include static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect) { flash_write_cmd (info, sect, AMD_ADDR_START, AMD_CMD_UNLOCK_START); flash_write_cmd (info, sect, AMD_ADDR_ACK, AMD_CMD_UNLOCK_ACK); } /*----------------------------------------------------------------------- * 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 amd_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, AMD_CMD_RESET); flash_unlock_seq(info, 0); flash_write_cmd(info, 0, AMD_ADDR_START, 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); if (info->device_id == 0x7E) { /* AMD 3-byte (expanded) device ids */ info->device_id2 = flash_read_uchar (info, FLASH_OFFSET_DEVICE_ID2); info->device_id2 <<= 8; info->device_id2 |= flash_read_uchar (info, FLASH_OFFSET_DEVICE_ID3); } flash_write_cmd(info, 0, 0, AMD_CMD_RESET); } static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd) { cfiptr_t cptr; cfiword_t cword; int retval; cptr.cp = flash_make_addr (info, sect, offset); flash_make_cmd (info, cmd, &cword); switch (info->portwidth) { case FLASH_CFI_8BIT: retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c)); break; case FLASH_CFI_16BIT: retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w)); break; case FLASH_CFI_32BIT: retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l)); break; case FLASH_CFI_64BIT: retval = ((cptr.llp[0] & cword.ll) != (cptr.llp[0] & cword.ll)); break; default: retval = 0; break; } 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 amd_flash_is_busy (flash_info_t * info, flash_sect_t sect) { return flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE); } static int amd_flash_erase_one (flash_info_t * info, long sect) { int rcode = 0; flash_unlock_seq (info, sect); flash_write_cmd (info, sect, AMD_ADDR_ERASE_START, AMD_CMD_ERASE_START); flash_unlock_seq (info, sect); flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR); if (flash_status_check (info, sect, info->erase_blk_tout, "erase")) { rcode = 1; } else putc ('.'); return rcode; } static void amd_flash_prepare_write(flash_info_t * info) { flash_unlock_seq (info, 0); flash_write_cmd (info, 0, AMD_ADDR_START, AMD_CMD_WRITE); } #ifdef CONFIG_CFI_BUFFER_WRITE static int amd_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_unlock_seq(info,0); flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER); switch (info->portwidth) { case FLASH_CFI_8BIT: cnt = len; flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) *dst.cp++ = *src.cp++; break; case FLASH_CFI_16BIT: cnt = len >> 1; flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) *dst.wp++ = *src.wp++; break; case FLASH_CFI_32BIT: cnt = len >> 2; flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) *dst.lp++ = *src.lp++; break; case FLASH_CFI_64BIT: cnt = len >> 3; flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) *dst.llp++ = *src.llp++; break; default: return ERR_INVAL; } flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM); retcode = flash_status_check (info, sector, info->buffer_write_tout, "buffer write"); return retcode; } #endif /* CONFIG_CFI_BUFFER_WRITE */ struct cfi_cmd_set cfi_cmd_set_amd = { .flash_write_cfibuffer = amd_flash_write_cfibuffer, .flash_erase_one = amd_flash_erase_one, .flash_is_busy = amd_flash_is_busy, .flash_read_jedec_ids = amd_read_jedec_ids, .flash_prepare_write = amd_flash_prepare_write, };