* 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
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)) {
 				/*
-				 * 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".
+				 * 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 {
+				/*
+				 * 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 */