@ -64,7 +64,6 @@ typedef volatile unsigned char FLASH_PORT_WIDTHV;
# define FLASH_CYCLE2 0x02aa
# define WR_BLOCK 0x20
/*-----------------------------------------------------------------------
* Functions
*/
@ -74,6 +73,9 @@ static int write_data_block (flash_info_t * info, ulong src, ulong dest);
static int write_word_amd ( flash_info_t * info , FPWV * dest , FPW data ) ;
static void flash_get_offsets ( ulong base , flash_info_t * info ) ;
void inline spin_wheel ( void ) ;
static void flash_sync_real_protect ( flash_info_t * info ) ;
static unsigned char intel_sector_protected ( flash_info_t * info , ushort sector ) ;
static unsigned char same_chip_banks ( int bank1 , int bank2 ) ;
/*-----------------------------------------------------------------------
*/
@ -115,6 +117,9 @@ unsigned long flash_init (void)
break ;
}
size + = flash_info [ i ] . size ;
/* get the h/w and s/w protection status in sync */
flash_sync_real_protect ( & flash_info [ i ] ) ;
}
/* Protect monitor and environment sectors
@ -167,7 +172,6 @@ static void flash_get_offsets (ulong base, flash_info_t * info)
if ( ( info - > flash_id & FLASH_VENDMASK ) = = FLASH_MAN_INTEL ) {
for ( i = 0 ; i < info - > sector_count ; i + + ) {
info - > start [ i ] = base + ( i * PHYS_INTEL_SECT_SIZE ) ;
info - > protect [ i ] = 0 ;
}
}
}
@ -305,6 +309,98 @@ static ulong flash_get_size (FPW * addr, flash_info_t * info)
}
/*
* This function gets the u - boot flash sector protection status
* ( flash_info_t . protect [ ] ) in sync with the sector protection
* status stored in hardware .
*/
static void flash_sync_real_protect ( flash_info_t * info )
{
int i ;
switch ( info - > flash_id & FLASH_TYPEMASK ) {
case FLASH_28F128J3A :
for ( i = 0 ; i < info - > sector_count ; + + i ) {
info - > protect [ i ] = intel_sector_protected ( info , i ) ;
}
break ;
case FLASH_AM040 :
default :
/* no h/w protect support */
break ;
}
}
/*
* checks if " sector " in bank " info " is protected . Should work on intel
* strata flash chips 28F xxxJ3x in 8 - bit mode .
* Returns 1 if sector is protected ( or timed - out while trying to read
* protection status ) , 0 if it is not .
*/
static unsigned char intel_sector_protected ( flash_info_t * info , ushort sector )
{
FPWV * addr ;
FPWV * lock_conf_addr ;
ulong start ;
unsigned char ret ;
/*
* first , wait for the WSM to be finished . The rationale for
* waiting for the WSM to become idle for at most
* CFG_FLASH_ERASE_TOUT is as follows . The WSM can be busy
* because of : ( 1 ) erase , ( 2 ) program or ( 3 ) lock bit
* configuration . So we just wait for the longest timeout of
* the ( 1 ) - ( 3 ) , i . e . the erase timeout .
*/
/* wait at least 35ns (W12) before issuing Read Status Register */
udelay ( 1 ) ;
addr = ( FPWV * ) info - > start [ sector ] ;
* addr = ( FPW ) INTEL_STATUS ;
start = get_timer ( 0 ) ;
while ( ( * addr & ( FPW ) INTEL_FINISHED ) ! = ( FPW ) INTEL_FINISHED ) {
if ( get_timer ( start ) > CFG_FLASH_ERASE_TOUT ) {
* addr = ( FPW ) INTEL_RESET ; /* restore read mode */
printf ( " WSM busy too long, can't get prot status \n " ) ;
return 1 ;
}
}
/* issue the Read Identifier Codes command */
* addr = ( FPW ) INTEL_READID ;
/* wait at least 35ns (W12) before reading */
udelay ( 1 ) ;
/* Intel example code uses offset of 4 for 8-bit flash */
lock_conf_addr = ( FPWV * ) info - > start [ sector ] + 4 ;
ret = ( * lock_conf_addr & ( FPW ) INTEL_PROTECT ) ? 1 : 0 ;
/* put flash back in read mode */
* addr = ( FPW ) INTEL_RESET ;
return ret ;
}
/*
* Checks if " bank1 " and " bank2 " are on the same chip . Returns 1 if they
* are and 0 otherwise .
*/
static unsigned char same_chip_banks ( int bank1 , int bank2 )
{
unsigned char same_chip [ CFG_MAX_FLASH_BANKS ] [ CFG_MAX_FLASH_BANKS ] = {
{ 1 , 1 , 0 , 0 } ,
{ 1 , 1 , 0 , 0 } ,
{ 0 , 0 , 1 , 1 } ,
{ 0 , 0 , 1 , 1 }
} ;
return same_chip [ bank1 ] [ bank2 ] ;
}
/*-----------------------------------------------------------------------
*/
int flash_erase ( flash_info_t * info , int s_first , int s_last )
@ -729,7 +825,9 @@ void inline spin_wheel (void)
int flash_real_protect ( flash_info_t * info , long sector , int prot )
{
ulong start ;
int i ;
int i , j ;
int curr_bank ;
int bank ;
int rc = 0 ;
FPWV * addr = ( FPWV * ) ( info - > start [ sector ] ) ;
int flag = disable_interrupts ( ) ;
@ -779,23 +877,54 @@ int flash_real_protect (flash_info_t * info, long sector, int prot)
* we have to restore lock bits of protected sectors .
*/
if ( ! prot ) {
for ( i = 0 ; i < info - > sector_count ; i + + ) {
if ( info - > protect [ i ] ) {
start = get_timer ( 0 ) ;
addr = ( FPWV * ) ( info - > start [ i ] ) ;
* addr = INTEL_LOCKBIT ; /* Sector lock bit */
* addr = INTEL_PROTECT ; /* set */
while ( ( * addr & INTEL_FINISHED ) ! =
INTEL_FINISHED ) {
if ( get_timer ( start ) >
CFG_FLASH_UNLOCK_TOUT ) {
printf ( " Flash lock bit operation timed out \n " ) ;
rc = 1 ;
break ;
/*
* re - locking must be done for all banks that belong on one
* FLASH chip , as all the sectors on the chip were unlocked
* by INTEL_LOCKBIT / INTEL_CONFIRM commands . ( let ' s hope
* that banks never span chips , in particular chips which
* support h / w protection differently ) .
*/
/* find the current bank number */
curr_bank = CFG_MAX_FLASH_BANKS + 1 ;
for ( j = 0 ; j < CFG_MAX_FLASH_BANKS ; + + j ) {
if ( & flash_info [ j ] = = info ) {
curr_bank = j ;
}
}
if ( curr_bank = = CFG_MAX_FLASH_BANKS + 1 ) {
printf ( " Error: can't determine bank number! \n " ) ;
}
for ( bank = 0 ; bank < CFG_MAX_FLASH_BANKS ; + + bank ) {
if ( ! same_chip_banks ( curr_bank , bank ) ) {
continue ;
}
info = & flash_info [ bank ] ;
for ( i = 0 ; i < info - > sector_count ; i + + ) {
if ( info - > protect [ i ] ) {
start = get_timer ( 0 ) ;
addr = ( FPWV * ) ( info - > start [ i ] ) ;
* addr = INTEL_LOCKBIT ; /* Sector lock bit */
* addr = INTEL_PROTECT ; /* set */
while ( ( * addr & INTEL_FINISHED ) ! =
INTEL_FINISHED ) {
if ( get_timer ( start ) >
CFG_FLASH_UNLOCK_TOUT ) {
printf ( " Flash lock bit operation timed out \n " ) ;
rc = 1 ;
break ;
}
}
}
}
}
/*
* get the s / w sector protection status in sync with the h / w ,
* in case something went wrong during the re - locking .
*/
flash_sync_real_protect ( info ) ; /* resets flash to read mode */
}
if ( flag )