Hello all,
I'm having troubles with an AMD Mirror Bit Write Buffer Programing
algorythm I have written for U-Boot. I'm hoping that someone can provide
some insight to the problem. We are using an Am29LV320MB part and
according to the data sheet I am doing everything correctly (at least I
think I am ). So if someone could confirm my code is valid or wrong I
would appreciate it.
I am having troubles with the flash part decraring it has timed out. It
does complete the first buffer programing sequence and all programed
data is valid. If I force it to continue only the first buffer write to
each sector is programed.
My problems may be due to a bad chip. This is a prototype and we had
some issues with the power supply that may have dammaged the chip. I
doubt this because our Jtag debugger programs this part in write buffer
mode just fine.
Below is the two functions of intrest and I have attached the full
flash.c file.
/************* Begin code *****************/
#ifdef WRITE_BUFFER_PROG
int write_buffer_program(flash_info_t *info, ulong dest, char *src);
#endif
/*-----------------------------------------------------------------------
* Copy memory to flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
ulong cp, wp, data;
int i, l, rc;
wp = (addr & ~3); /* get lower word aligned address */
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
for (; i<4 && cnt>0; ++i) {
data = (data << 8) | *src++;
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4) {
#ifdef WRITE_BUFFER_PROG
if((cnt>=32)& !(wp & 0x1F)) { /* if destination is aligned on 32
byte boundry use write burst */
if ((rc = write_buffer_program(info,wp,src)) != 0) {
return (rc);
}
wp += 32;
src += 32;
cnt -= 32;
} else
#endif
{
data = 0;
for (i=0; i<4; ++i) {
data = (data << 8) | *src++;
}
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 4;
cnt -= 4;
}
}
if (cnt == 0) {
return (0);
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
data = (data << 8) | *src++;
--cnt;
}
for (; i<4; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
return (write_word(info, wp, data));
}
#ifdef WRITE_BUFFER_PROG
/*-----------------------------------------------------------------------
* Write a bunch of word to Flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
* 3 - write buffer abort
*/
int write_buffer_program(flash_info_t *info, ulong dest, char *src)
{
volatile CFG_FLASH_WORD_SIZE *target_sector;
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE
*)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)src;
CFG_FLASH_WORD_SIZE progstat;
ulong start;
int flag;
int i,j;
j=info->sector_count -1;
/*find sector start address to program*/
while(info->start[j] > dest) j--;
target_sector = (CFG_FLASH_WORD_SIZE *)(info->start[j]);
/* Check if Flash is (sufficiently) erased */
/* if ((*dest2 & *data2) != *data2) {
return (2);
} */
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
target_sector[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00250025; /*
write to buffer command */
/*write count of words to buffer minus 1 */
target_sector[CFG_FLASH_ADDR0] = (32/sizeof(CFG_FLASH_WORD_SIZE)) - 1 ;
/*write first word */
/* dest2[0] = data2[0]; */
/* write the rest */
i=0;
do
{
dest2[i] = data2[i];
i++;
}while(i<(32/sizeof(CFG_FLASH_WORD_SIZE)));
/*write buffer command */
target_sector[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00290029;
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* data polling for D7 */
i--; /* decrement index to point to last word written */
start = get_timer (0);
while( ((progstat=dest2[i]) & (CFG_FLASH_WORD_SIZE)0x00800080) !=
/*check for chip time out or abort*/
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ){
if(progstat & (CFG_FLASH_WORD_SIZE)0x00220022) {
if(progstat & (CFG_FLASH_WORD_SIZE)0x00200020){ /*check for chip
time out*/
/* return success if it really did work */
if( (dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ==
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ) return 0;
data2[i] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /*
reset flash chip */
printf("TimeOut\n"); /* for debugging only, remove */
return 1;
}
/* return success if it really did work */
if( (dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ==
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ) return 0;
/* if your here it is an abort condition */
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* Write
buffer abort reset */
printf("abort\n"); /* for debugging only, remove */
return 3;
}
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
return (1); /* U-Boot timer time out */
}
}
return (0);
}
#endif /* WRITE_BUFFER_PROG */
/*********** End code *********/
Thanks
Conn Clark
--
*****************************************************************
If you live at home long enough, your parents will move out.
(Warning they may try to sell their house out from under you.)
*****************************************************************
Conn Clark
Engineering Stooge clark@esteem.com
Electronic Systems Technology Inc. www.esteem.com
Stock Ticker Symbol ELST
"clark@esteem.com" Copyright 2000 By Electronic Systems Technology
This email address may be used to communicate to Conn Clark
provided it is not being used for advertisement purposes, unless
prior written consent is given. This email address may not be
sold under any circumstances. All other rights reserved.
/*
* (C) Copyright 2001
* Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
*
* (C) Copyright 2004
* Conn Clark, Electronic Systems Technology USA, clark@esteem.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <ppc4xx.h>
#include <asm/processor.h>
flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
/*-----------------------------------------------------------------------
* Functions
*/
ulong flash_get_size (vu_long * addr, flash_info_t * info);
void flash_get_offsets (ulong base, flash_info_t * info);
/*-----------------------------------------------------------------------
*/
unsigned long flash_init (void)
{
unsigned long size_b0;
int i;
uint pbcr;
unsigned long base_b0;
int size_val = 0;
/* Init: no FLASHes known */
for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
flash_info[i].flash_id = FLASH_UNKNOWN;
}
/* Static FLASH Bank configuration here - FIXME XXX */
size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
if (flash_info[0].flash_id == FLASH_UNKNOWN) {
printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
size_b0, size_b0<<20);
}
/* Setup offsets */
flash_get_offsets (-size_b0, &flash_info[0]);
/* Re-do sizing to get full correct info */
mtdcr(ebccfga, pb0cr);
pbcr = mfdcr(ebccfgd);
mtdcr(ebccfga, pb0cr);
base_b0 = -size_b0;
switch (size_b0) {
case 1 << 20:
size_val = 0;
break;
case 2 << 20:
size_val = 1;
break;
case 4 << 20:
size_val = 2;
break;
case 8 << 20:
size_val = 3;
break;
case 16 << 20:
size_val = 4;
break;
}
pbcr = (pbcr & 0x0001ffff) | base_b0 | (size_val << 17);
mtdcr(ebccfgd, pbcr);
/* Monitor protection ON by default */
(void)flash_protect(FLAG_PROTECT_SET,
-CFG_MONITOR_LEN,
0xffffffff,
&flash_info[0]);
flash_info[0].size = size_b0;
return (size_b0);
}
/*-----------------------------------------------------------------------
*/
void flash_get_offsets (ulong base, flash_info_t *info)
{
int i;
short n;
/* set up sector start address table */
if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV320MB) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV640MB)) {
/* set sector offsets for bottom boot block type */
for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */
info->start[i] = base;
base += 8 << 10;
}
while (i < info->sector_count) { /* 64k regular sectors */
info->start[i] = base;
base += 64 << 10;
++i;
}
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV320MT) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV640MT)) {
/* set sector offsets for top boot block type */
base += info->size;
i = info->sector_count;
for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */
base -= 8 << 10;
--i;
info->start[i] = base;
}
while (i > 0) { /* 64k regular sectors */
base -= 64 << 10;
--i;
info->start[i] = base;
}
} else {
if (info->flash_id & FLASH_BTYPE) {
/* set sector offsets for bottom boot block type */
info->start[0] = base + 0x00000000;
info->start[1] = base + 0x00004000;
info->start[2] = base + 0x00006000;
info->start[3] = base + 0x00008000;
for (i = 4; i < info->sector_count; i++) {
info->start[i] = base + (i * 0x00010000) - 0x00030000;
}
} else {
/* set sector offsets for top boot block type */
i = info->sector_count - 1;
info->start[i--] = base + info->size - 0x00004000;
info->start[i--] = base + info->size - 0x00006000;
info->start[i--] = base + info->size - 0x00008000;
for (; i >= 0; i--) {
info->start[i] = base + i * 0x00010000;
}
}
}
}
/*-----------------------------------------------------------------------
*/
void flash_print_info (flash_info_t *info)
{
int i;
int k;
int size;
int erased;
volatile unsigned long *flash;
if (info->flash_id == FLASH_UNKNOWN) {
printf ("missing or unknown FLASH type\n");
return;
}
switch (info->flash_id & FLASH_VENDMASK) {
case FLASH_MAN_AMD: printf ("AMD "); break;
default: printf ("Unknown Vendor "); break;
}
switch (info->flash_id & FLASH_TYPEMASK) {
case FLASH_AMLV320MT: printf ("AM29LV320MT (32 M, top sector)\n");
break;
case FLASH_AMLV320MB: printf ("AM29LV320MB (32 M, bottom sector)\n");
break;
case FLASH_AMLV640MT: printf ("AM29LV640MT (64 M, top boot sector)\n");
break;
case FLASH_AMLV640MB: printf ("AM29LV640MB (64 M, bottom boot sector)\n");
break;
default: printf ("Unknown Chip Type\n");
break;
}
printf (" Size: %ld MB in %d Sectors\n",
info->size >> 20, info->sector_count);
printf (" Sector Start Addresses:");
for (i=0; i<info->sector_count; ++i) {
#ifdef CFG_FLASH_EMPTY_INFO
/*
* Check if whole sector is erased
*/
if (i != (info->sector_count-1))
size = info->start[i+1] - info->start[i];
else
size = info->start[0] + info->size - info->start[i];
erased = 1;
flash = (volatile unsigned long *)info->start[i];
size = size >> 2; /* divide by 4 for longword access */
for (k=0; k<size; k++)
{
if (*flash++ != 0xffffffff)
{
erased = 0;
break;
}
}
if ((i % 5) == 0)
printf ("\n ");
/* print empty and read-only info */
printf (" %08lX%s%s",
info->start[i],
erased ? " E" : " ",
info->protect[i] ? "RO " : " ");
#else
if ((i % 5) == 0)
printf ("\n ");
printf (" %08lX%s",
info->start[i],
info->protect[i] ? " (RO)" : " ");
#endif
}
printf ("\n");
return;
}
/*-----------------------------------------------------------------------
*/
/*-----------------------------------------------------------------------
*/
/*
* The following code cannot be run from FLASH!
*/
ulong flash_get_size (vu_long *addr, flash_info_t *info)
{
short i;
short n;
CFG_FLASH_WORD_SIZE value,value2,value3;
ulong base = (ulong)addr;
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)addr;
/* Write auto select command: read Manufacturer ID */
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
value = addr2[CFG_FLASH_READ0];
switch (value) {
case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT:
info->flash_id = FLASH_MAN_AMD;
break;
default:
info->flash_id = FLASH_UNKNOWN;
info->sector_count = 0;
info->size = 0;
return (0); /* no or unknown flash */
}
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
value = addr2[CFG_FLASH_READ1]; /* device ID */
value2 = addr2[CFG_FLASH_READ14];
value3 = addr2[CFG_FLASH_READ15];
switch (value2) {
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320MTB_2:
info->sector_count = 71;
info->size = 0x00400000; /* => 4 MB */
if(value3==AMD_ID_LV320MT_3)
info->flash_id += FLASH_AMLV320MT;
else
info->flash_id += FLASH_AMLV320MB;
break;
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV640MTB_2:
info->sector_count = 135;
info->size = 0x00800000; /* => 4 MB */
if(value3==AMD_ID_LV320MT_3)
info->flash_id += FLASH_AMLV640MT;
else
info->flash_id += FLASH_AMLV640MB;
break;
default:
info->flash_id = FLASH_UNKNOWN;
return (0); /* => no or unknown flash */
}
/* set up sector start address table */
if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV320MB) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV640MB)) {
/* set sector offsets for bottom boot block type */
for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */
info->start[i] = base;
base += 8 << 10;
}
while (i < info->sector_count) { /* 64k regular sectors */
info->start[i] = base;
base += 64 << 10;
++i;
}
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV320MT) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV640MT)) {
/* set sector offsets for top boot block type */
base += info->size;
i = info->sector_count;
for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */
base -= 8 << 10;
--i;
info->start[i] = base;
}
while (i > 0) { /* 64k regular sectors */
base -= 64 << 10;
--i;
info->start[i] = base;
}
}
/* check for protected sectors */
for (i = 0; i < info->sector_count; i++) {
/* Write auto select command: read protection status */
addr2 = (CFG_FLASH_WORD_SIZE *)info->start[i];
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
/* read sector protection at sector address, (A7 .. A0) = 0x02 */
/* D0 = 1 if protected */
info->protect[i] = addr2[CFG_FLASH_READ2] & 1;
}
/*
* Prevent writes to uninitialized FLASH.
*/
if (info->flash_id != FLASH_UNKNOWN) {
addr2 = (CFG_FLASH_WORD_SIZE *)info->start[0];
*addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
}
return (info->size);
}
/*-----------------------------------------------------------------------
*/
int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *addr2;
int flag, prot, sect, l_sect;
ulong start, now, last;
if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN) {
printf ("- missing\n");
} else {
printf ("- no sectors to erase\n");
}
return 1;
}
if (info->flash_id == FLASH_UNKNOWN) {
printf ("Can't erase unknown flash type - aborted\n");
return 1;
}
prot = 0;
for (sect=s_first; sect<=s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
if (prot) {
printf ("- Warning: %d protected sectors will not be erased!\n",
prot);
} else {
printf ("\n");
}
l_sect = -1;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]);
if (sect == s_first) {
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
}
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */
l_sect = sect;
}
}
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* wait at least 80us - let's wait 1 ms */
udelay (1000);
/*
* We wait for the last triggered sector
*/
if (l_sect < 0)
goto DONE;
start = get_timer (0);
last = start;
addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]);
while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
putc ('.');
last = now;
}
}
DONE:
/* reset to read mode */
addr = (CFG_FLASH_WORD_SIZE *)info->start[0];
addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
printf (" done\n");
return 0;
}
/*-----------------------------------------------------------------------
* Functions
*/
/*#define WRITE_BUFFER_PROG 1 */
int write_word (flash_info_t *info, ulong dest, ulong data);
#ifdef WRITE_BUFFER_PROG
int write_buffer_program(flash_info_t *info, ulong dest, char *src);
#endif
/*-----------------------------------------------------------------------
* Copy memory to flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
ulong cp, wp, data;
int i, l, rc;
wp = (addr & ~3); /* get lower word aligned address */
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
for (; i<4 && cnt>0; ++i) {
data = (data << 8) | *src++;
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4) {
#ifdef WRITE_BUFFER_PROG
if((cnt>=32)& !(wp & 0x1F)) { /* if destination is aligned on 32 byte boundry use write burst */
if ((rc = write_buffer_program(info,wp,src)) != 0) {
return (rc);
}
wp += 32;
src += 32;
cnt -= 32;
} else
#endif
{
data = 0;
for (i=0; i<4; ++i) {
data = (data << 8) | *src++;
}
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 4;
cnt -= 4;
}
}
if (cnt == 0) {
return (0);
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
data = (data << 8) | *src++;
--cnt;
}
for (; i<4; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
return (write_word(info, wp, data));
}
/*-----------------------------------------------------------------------
* Write a word to Flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
int write_word (flash_info_t *info, ulong dest, ulong data)
{
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data;
ulong start;
int flag;
int i;
/* Check if Flash is (sufficiently) erased */
if ((*((volatile CFG_FLASH_WORD_SIZE *)dest) &
(CFG_FLASH_WORD_SIZE)data) != (CFG_FLASH_WORD_SIZE)data) {
return (2);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++)
{
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;
dest2[i] = data2[i];
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* data polling for D7 */
start = get_timer (0);
while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) {
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
return (1);
}
}
}
return (0);
}
#ifdef WRITE_BUFFER_PROG
/*-----------------------------------------------------------------------
* Write a bunch of word to Flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
* 3 - write buffer abort
*/
int write_buffer_program(flash_info_t *info, ulong dest, char *src)
{
volatile CFG_FLASH_WORD_SIZE *target_sector;
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)src;
CFG_FLASH_WORD_SIZE progstat;
ulong start;
int flag;
int i,j;
j=info->sector_count -1;
/*find sector start address to program*/
while(info->start[j] > dest) j--;
target_sector = (CFG_FLASH_WORD_SIZE *)(info->start[j]);
/* Check if Flash is (sufficiently) erased */
/* if ((*dest2 & *data2) != *data2) {
return (2);
} */
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
target_sector[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00250025; /* write to buffer command */
/*write count of words to buffer minus 1 */
target_sector[CFG_FLASH_ADDR0] = (32/sizeof(CFG_FLASH_WORD_SIZE)) - 1 ;
/*write first word */
/* dest2[0] = data2[0]; */
/* write the rest */
i=0;
do
{
dest2[i] = data2[i];
i++;
}while(i<(32/sizeof(CFG_FLASH_WORD_SIZE)));
/*write buffer command */
target_sector[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00290029;
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* data polling for D7 */
i--; /* decrement index to point to last word written */
start = get_timer (0);
while( ((progstat=dest2[i]) & (CFG_FLASH_WORD_SIZE)0x00800080) !=
/*check for chip time out or abort*/
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ){
if(progstat & (CFG_FLASH_WORD_SIZE)0x00220022) {
if(progstat & (CFG_FLASH_WORD_SIZE)0x00200020){ /*check for chip time out*/
/* return success if it really did work */
if( (dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ==
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ) return 0;
data2[i] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset flash chip */
printf("TimeOut\n"); /* for debugging only, remove */
return 1;
}
/* return success if it really did work */
if( (dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ==
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) ) return 0;
/* if your here it is an abort condition */
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* Write buffer abort reset */
printf("abort\n"); /* for debugging only, remove */
return 3;
}
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
return (1); /* U-Boot timer time out */
}
}
return (0);
}
#endif /* WRITE_BUFFER_PROG */
/*-----------------------------------------------------------------------
*/