svn_rev_351
This commit is contained in:
parent
cc43d146a8
commit
52f6ce11a9
|
@ -0,0 +1,158 @@
|
|||
#include <cfi_flash.h>
|
||||
|
||||
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,
|
||||
};
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
#include <cfi_flash.h>
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* 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,
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue