Merge with /home/sr/git/u-boot/cfi-flash
diff --git a/CHANGELOG b/CHANGELOG
index 59f12b8..5040a6b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,33 @@
 Changes since U-Boot 1.1.4:
 ======================================================================
 
+* Changes/fixes for drivers/cfi_flash.c:
+
+  - Add Intel legacy lock/unlock support to common CFI driver
+
+    On some Intel flash's (e.g. Intel J3) legacy unlocking is
+    supported, meaning that unlocking of one sector will unlock
+    all sectors of this bank. Using this feature, unlocking
+    of all sectors upon startup (via env var "unlock=yes") will
+    get much faster.
+
+  - Fixed problem with multiple reads of envronment variable
+    "unlock" as pointed out by Reinhard Arlt & Anders Larsen.
+
+  - Removed unwanted linefeeds from "protect" command when
+    CFG_FLASH_PROTECTION is enabled.
+
+  - Changed p3p400 board to use CFG_FLASH_PROTECTION
+
+  Patch by Stefan Roese, 01 Apr 2006
+
+* Changes/fixes for drivers/cfi_flash.c:
+  - Correctly handle the cases where CFG_HZ != 1000 (several
+    XScale-based boards)
+  - Fix the timeout calculation of buffered writes (off by a
+    factor of 1000)
+  Patch by Anders Larsen, 31 Mar 2006
+
 * Updates to common PPC4xx onboard (DDR)SDRAM init code (405 and 440)
 
   405 SDRAM: - The SDRAM parameters can now be defined in the board
diff --git a/common/cmd_flash.c b/common/cmd_flash.c
index 0aa4783..201f4e3 100644
--- a/common/cmd_flash.c
+++ b/common/cmd_flash.c
@@ -455,6 +455,7 @@
 #ifdef CONFIG_HAS_DATAFLASH
 	int status;
 #endif
+
 	if (argc < 3) {
 		printf ("Usage:\n%s\n", cmdtp->usage);
 		return 1;
@@ -655,10 +656,10 @@
 #endif	/* CFG_FLASH_PROTECTION */
 				}
 			}
+		}
 #if defined(CFG_FLASH_PROTECTION)
-			if (!rcode) putc ('\n');
+		puts (" done\n");
 #endif	/* CFG_FLASH_PROTECTION */
-		}
 
 		printf ("%sProtected %d sectors\n",
 			p ? "" : "Un-", protected);
diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c
index a989d34..2e37480 100644
--- a/drivers/cfi_flash.c
+++ b/drivers/cfi_flash.c
@@ -117,6 +117,7 @@
 #define FLASH_OFFSET_CFI		0x55
 #define FLASH_OFFSET_CFI_RESP		0x10
 #define FLASH_OFFSET_PRIMARY_VENDOR	0x13
+#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR	0x15	/* extended query table primary addr */
 #define FLASH_OFFSET_WTOUT		0x1F
 #define FLASH_OFFSET_WBTOUT		0x20
 #define FLASH_OFFSET_ETOUT		0x21
@@ -346,6 +347,10 @@
 	unsigned long size = 0;
 	int i;
 
+#ifdef CFG_FLASH_PROTECTION
+	char *s = getenv("unlock");
+#endif
+
 	/* Init: no FLASHes known */
 	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
 		flash_info[i].flash_id = FLASH_UNKNOWN;
@@ -357,15 +362,39 @@
 #endif /* CFG_FLASH_QUIET_TEST */
 		}
 #ifdef CFG_FLASH_PROTECTION
-		else {
-			char *s = getenv("unlock");
+		else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
+			/*
+			 * Only the U-Boot image and it's environment is protected,
+			 * all other sectors are unprotected (unlocked) if flash
+			 * hardware protection is used (CFG_FLASH_PROTECTION) and
+			 * the environment variable "unlock" is set to "yes".
+			 */
+			if (flash_info[i].legacy_unlock) {
+				int k;
 
-			if (((s = getenv("unlock")) != NULL) && (strcmp(s, "yes") == 0)) {
+				/*
+				 * Disable legacy_unlock temporarily, since
+				 * flash_real_protect would relock all other sectors
+				 * again otherwise.
+				 */
+				flash_info[i].legacy_unlock = 0;
+
+				/*
+				 * Legacy unlocking (e.g. Intel J3) -> unlock only one
+				 * sector. This will unlock all sectors.
+				 */
+				flash_real_protect (&flash_info[i], 0, 0);
+
+				flash_info[i].legacy_unlock = 1;
+
+				/*
+				 * Manually mark other sectors as unlocked (unprotected)
+				 */
+				for (k = 1; k < flash_info[i].sector_count; k++)
+					flash_info[i].protect[k] = 0;
+			} else {
 				/*
-				 * Only the U-Boot image and it's environment is protected,
-				 * all other sectors are unprotected (unlocked) if flash
-				 * hardware protection is used (CFG_FLASH_PROTECTION) and
-				 * the environment variable "unlock" is set to "yes".
+				 * No legancy unlocking -> unlock all sectors
 				 */
 				flash_protect (FLAG_PROTECT_CLEAR,
 					       flash_info[i].start[0],
@@ -668,8 +697,12 @@
 				      prot ? "protect" : "unprotect")) == 0) {
 
 		info->protect[sector] = prot;
-		/* Intel's unprotect unprotects all locking */
-		if (prot == 0) {
+
+		/*
+		 * On some of Intel's flash chips (marked via legacy_unlock)
+		 * unprotect unprotects all locking.
+		 */
+		if ((prot == 0) && (info->legacy_unlock)) {
 			flash_sect_t i;
 
 			for (i = 0; i < info->sector_count; i++) {
@@ -746,6 +779,10 @@
 {
 	ulong start;
 
+#if CFG_HZ != 1000
+	tout *= CFG_HZ/1000;
+#endif
+
 	/* Wait for command completion */
 	start = get_timer (0);
 	while (flash_is_busy (info, sector)) {
@@ -1082,6 +1119,10 @@
 	uchar num_erase_regions;
 	int erase_region_size;
 	int erase_region_count;
+#ifdef CFG_FLASH_PROTECTION
+	int ext_addr;
+	info->legacy_unlock = 0;
+#endif
 
 	info->start[0] = base;
 
@@ -1095,6 +1136,13 @@
 		case CFI_CMDSET_INTEL_EXTENDED:
 		default:
 			info->cmd_reset = FLASH_CMD_RESET;
+#ifdef CFG_FLASH_PROTECTION
+			/* read legacy lock/unlock bit from intel flash */
+			ext_addr = flash_read_ushort (info, 0,
+						      FLASH_OFFSET_EXT_QUERY_T_P_ADDR);
+			info->legacy_unlock =
+				flash_read_uchar (info, ext_addr + 5) & 0x08;
+#endif
 			break;
 		case CFI_CMDSET_AMD_STANDARD:
 		case CFI_CMDSET_AMD_EXTENDED:
@@ -1160,8 +1208,9 @@
 		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_WBTOUT)) *
+			(1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT));
+		info->buffer_write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
 		tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) *
 		      (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT));
 		info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
diff --git a/include/configs/p3p440.h b/include/configs/p3p440.h
index 0662544..aa0901f 100644
--- a/include/configs/p3p440.h
+++ b/include/configs/p3p440.h
@@ -147,6 +147,7 @@
 		"cp.b 100000 fffc0000 40000;"			        \
 		"setenv filesize;saveenv\0"				\
 	"upd=run load;run update\0"					\
+	"unlock=yes\0"							\
 	""
 #define CONFIG_BOOTCOMMAND	"run net_nfs"
 
@@ -277,7 +278,7 @@
 #define CFG_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/
 
 #define CFG_FLASH_USE_BUFFER_WRITE 1	/* use buffered writes (20x faster)	*/
-#define CFG_FLASH_PROTECTION	1	/* hardware flash protection		*/
+#define CFG_FLASH_PROTECTION	1	/* use hardware flash protection	*/
 
 #define CFG_FLASH_EMPTY_INFO		/* print 'E' for empty sector on flinfo */
 #define CFG_FLASH_QUIET_TEST	1	/* don't warn upon unknown flash	*/
diff --git a/include/flash.h b/include/flash.h
index 4c68c68..a84dc68 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -45,6 +45,7 @@
 	ushort	vendor;			/* the primary vendor id		*/
 	ushort	cmd_reset;		/* Vendor specific reset command	*/
 	ushort	interface;		/* used for x8/x16 adjustments		*/
+	ushort	legacy_unlock;		/* support Intel legacy (un)locking	*/
 #endif
 } flash_info_t;