diff options
| -rw-r--r-- | CHANGELOG | 11 | ||||
| -rw-r--r-- | board/alaska/flash.c | 161 | ||||
| -rw-r--r-- | board/dave/PPChameleonEVB/PPChameleonEVB.c | 2 | ||||
| -rw-r--r-- | board/pm520/flash.c | 97 | ||||
| -rw-r--r-- | include/configs/PPChameleonEVB.h | 2 | 
5 files changed, 253 insertions, 20 deletions
| @@ -14,6 +14,17 @@ Changes for U-Boot 1.1.3:    - Add support for AMCC Yosemite PPC440EP eval board.    - Add support for AMCC Yellowstone PPC440GR eval board. +* Minor fixes for PPChameleon Board: +  - fix alignment of NAND size +  - make code do what the comment says + +* Implement h/w sector protection status synchronization at boot. +  The code is provided for, and was tested on, the Yukon/Alaska +  and PM520 boards only. + +  A bug in flash_real_protect() for the Yukon board was fixed by +  adding a function that tells if two banks are on one flash chip. +  * Fix sysmon POST problem: check I2C error codes    This fixes a problem of displaying bogus voltages when the voltages    are so low that the I2C devices start failing while the rest of the diff --git a/board/alaska/flash.c b/board/alaska/flash.c index 48c94727e..383491f56 100644 --- a/board/alaska/flash.c +++ b/board/alaska/flash.c @@ -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 28FxxxJ3x 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) diff --git a/board/dave/PPChameleonEVB/PPChameleonEVB.c b/board/dave/PPChameleonEVB/PPChameleonEVB.c index 0bd43bd02..1f6512d0e 100644 --- a/board/dave/PPChameleonEVB/PPChameleonEVB.c +++ b/board/dave/PPChameleonEVB/PPChameleonEVB.c @@ -261,7 +261,7 @@ nand_init(void)  	debug ("Probing at 0x%.8x\n", CFG_NAND1_BASE);  	totlen += nand_probe (CFG_NAND1_BASE); -	printf ("%4lu MB\n", totlen >>20); +	printf ("%3lu MB\n", totlen >>20);  }  #endif diff --git a/board/pm520/flash.c b/board/pm520/flash.c index 572cc9bbe..62700f9f9 100644 --- a/board/pm520/flash.c +++ b/board/pm520/flash.c @@ -75,6 +75,8 @@ static ulong flash_get_size (FPW *addr, flash_info_t *info);  static int write_data (flash_info_t *info, ulong 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);  /*-----------------------------------------------------------------------   */ @@ -101,6 +103,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 @@ -138,7 +143,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_FLASH_SECT_SIZE); -			info->protect[i] = 0;  		}  	}  } @@ -270,6 +274,85 @@ 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: +	case FLASH_28F640J3A: +	case FLASH_28F320J3A: +		for (i = 0; i < info->sector_count; ++i) { +			info->protect[i] = intel_sector_protected(info, i); +		} +		break; +	default: +		/* no h/w protect support */ +		break; +	} +} + + +/* + * checks if "sector" in bank "info" is protected. Should work on intel + * strata flash chips 28FxxxJ3x 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 2 for 16 bit flash */ +	lock_conf_addr = (FPWV *) info->start[sector] + 2; +	ret = (*lock_conf_addr & (FPW) INTEL_PROTECT) ? 1 : 0; + +	/* put flash back in read mode */ +	*addr = (FPW) INTEL_RESET; + +	return ret; +} + + +  /*-----------------------------------------------------------------------   */ @@ -491,7 +574,7 @@ void inline spin_wheel (void)   * 0 - OK   * 1 - Error (timeout, voltage problems, etc.)   */ -int flash_real_protect(flash_info_t *info, long sector, int prot) +int flash_real_protect (flash_info_t *info, long sector, int prot)  {  	ulong start;  	int i; @@ -531,6 +614,11 @@ int flash_real_protect(flash_info_t *info, long sector, int prot)  	/*  	 * Clear lock bit command clears all sectors lock bits, so  	 * we have to restore lock bits of protected sectors. +	 * WARNING: code below re-locks sectors only for one bank (info). +	 * This causes problems on boards where several banks share +	 * the same chip, as sectors in othere banks will be unlocked +	 * but not re-locked. It works fine on pm520 though, as there +	 * is only one chip and one bank.  	 */  	if (!prot)  	{ @@ -553,6 +641,11 @@ int flash_real_protect(flash_info_t *info, long sector, int prot)  				}  			}  		} +		/* +		 * 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) diff --git a/include/configs/PPChameleonEVB.h b/include/configs/PPChameleonEVB.h index d7025eba6..ca0bd12f0 100644 --- a/include/configs/PPChameleonEVB.h +++ b/include/configs/PPChameleonEVB.h @@ -47,7 +47,7 @@   * CONFIG_PPCHAMELEON_CLK_33   */  #if (!defined(CONFIG_PPCHAMELEON_CLK_25) && !defined(CONFIG_PPCHAMELEON_CLK_33)) -#define CONFIG_PPCHAMELEON_CLK_33 +#define CONFIG_PPCHAMELEON_CLK_25  #endif  #if (defined(CONFIG_PPCHAMELEON_CLK_25) && defined(CONFIG_PPCHAMELEON_CLK_33)) |