Newer
Older
#ifdef DEBUG
flash_printqry (info, 0);
#endif
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
default:
info->cmd_reset = FLASH_CMD_RESET;
break;
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
info->cmd_reset = AMD_CMD_RESET;
break;
}
size_ratio = info->portwidth / info->chipwidth;
/* if the chip is x8/x16 reduce the ratio by half */
if ((info->interface == FLASH_CFI_X8X16)
&& (info->chipwidth == FLASH_CFI_BY8)) {
size_ratio >>= 1;
}
num_erase_regions = flash_read_uchar (info, FLASH_OFFSET_NUM_ERASE_REGIONS);
debug ("size_ratio %d port %d bits chip %d bits\n",
size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
debug ("found %d erase regions\n", num_erase_regions);
sect_cnt = 0;
sector = base;
for (i = 0; i < num_erase_regions; i++) {
if (i > NUM_ERASE_REGIONS) {
printf ("%d erase regions found, only %d used\n",
num_erase_regions, NUM_ERASE_REGIONS);
tmp = flash_read_long (info, 0,
FLASH_OFFSET_ERASE_REGIONS +
i * 4);
erase_region_size =
(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
debug ("erase_region_count = %d erase_region_size = %d\n",
erase_region_count, erase_region_size);
info->start[sect_cnt] = sector;
sector += (erase_region_size * size_ratio);
info->protect[sect_cnt] =
flash_isset (info, sect_cnt,
FLASH_OFFSET_PROTECT,
FLASH_STATUS_PROTECT);
sect_cnt++;
}
}
info->sector_count = sect_cnt;
/* multiply the size by the number of chips */
info->size = (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * size_ratio;
info->buffer_size = (1 << flash_read_ushort (info, 0, FLASH_OFFSET_BUFFER_SIZE));
tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT);
info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT);
info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT);
info->write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT))) / 1000;
if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
}
flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
return (info->size);
}
/*-----------------------------------------------------------------------
*/
static int flash_write_cfiword (flash_info_t * info, ulong dest,
cfiword_t cword)
{
cfiptr_t ctladdr;
cfiptr_t cptr;
int flag;
ctladdr.cp = flash_make_addr (info, 0, 0);
cptr.cp = (uchar *) dest;
/* Check if Flash is (sufficiently) erased */
case FLASH_CFI_8BIT:
flag = ((cptr.cp[0] & cword.c) == cword.c);
break;
case FLASH_CFI_16BIT:
flag = ((cptr.wp[0] & cword.w) == cword.w);
break;
case FLASH_CFI_32BIT:
break;
case FLASH_CFI_64BIT:
flag = ((cptr.lp[0] & cword.ll) == cword.ll);
break;
default:
return 2;
}
return 2;
/* Disable interrupts which might cause a timeout here */
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:
flash_write_cmd (info, 0, AMD_ADDR_START, AMD_CMD_WRITE);
case FLASH_CFI_8BIT:
cptr.cp[0] = cword.c;
break;
case FLASH_CFI_16BIT:
cptr.wp[0] = cword.w;
break;
case FLASH_CFI_32BIT:
cptr.lp[0] = cword.l;
break;
case FLASH_CFI_64BIT:
cptr.llp[0] = cword.ll;
break;
}
/* re-enable interrupts if necessary */
return flash_full_status_check (info, 0, info->write_tout, "write");
}
#ifdef CFG_FLASH_USE_BUFFER_WRITE
/* 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)
for (sector = info->sector_count - 1; sector >= 0; sector--) {
if (addr >= info->start[sector])
break;
}
return sector;
}
static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
int len)
{
flash_sect_t sector;
int cnt;
int retcode;
volatile cfiptr_t src;
volatile cfiptr_t dst;
/* buffered writes in the AMD chip set is not supported yet */
if((info->vendor == CFI_CMDSET_AMD_STANDARD) ||
(info->vendor == CFI_CMDSET_AMD_EXTENDED))
return ERR_INVAL;
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");
flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
#endif /* CFG_FLASH_USE_BUFFER_WRITE */