* The PS/2 mux on the BMS2003 board needs 450 ms after power on
  before we can access it; add delay in case we are faster (with no
  CF card inserted)

* Cleanup of some init functions

* Make sure SCC Ethernet is always stopped by the time we boot Linux
  to avoid Linux crashes by early packets coming in.

* Accelerate flash accesses on LWMON board by using buffered writes
diff --git a/board/lwmon/flash.c b/board/lwmon/flash.c
index 127738a..4004865 100644
--- a/board/lwmon/flash.c
+++ b/board/lwmon/flash.c
@@ -47,6 +47,9 @@
  */
 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
 static int write_data (flash_info_t *info, ulong dest, ulong data);
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+static int write_data_buf (flash_info_t * info, ulong dest, uchar * cp, int len);
+#endif
 static void flash_get_offsets (ulong base, flash_info_t *info);
 
 /*-----------------------------------------------------------------------
@@ -480,6 +483,17 @@
 	/*
 	 * handle FLASH_WIDTH aligned part
 	 */
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+	while(cnt >= FLASH_WIDTH) {
+		i = CFG_FLASH_BUFFER_SIZE > cnt ?
+		    (cnt & ~(FLASH_WIDTH - 1)) : CFG_FLASH_BUFFER_SIZE;
+		if((rc = write_data_buf(info, wp, src,i)) != 0)
+			return rc;
+		wp += i;
+		src += i;
+		cnt -=i;
+	}
+#else
 	while (cnt >= FLASH_WIDTH) {
 		data = 0;
 		for (i=0; i<FLASH_WIDTH; ++i) {
@@ -491,6 +505,7 @@
 		wp  += FLASH_WIDTH;
 		cnt -= FLASH_WIDTH;
 	}
+#endif /* CFG_FLASH_USE_BUFFER_WRITE */
 
 	if (cnt == 0) {
 		return (0);
@@ -512,6 +527,28 @@
 }
 
 /*-----------------------------------------------------------------------
+ * Check flash status, returns:
+ * 0 - OK
+ * 1 - timeout
+ */
+static int flash_status_check(vu_long *addr, ulong tout, char * prompt)
+{
+	ulong status;
+	ulong start;
+
+	/* Wait for command completion */
+	start = get_timer (0);
+	while(((status = *addr) & 0x00800080) != 0x00800080) {
+		if (get_timer(start) > tout) {
+			printf("Flash %s timeout at address %p\n", prompt, addr);
+			*addr = 0x00FF00FF;	/* restore read mode */
+			return (1);
+		}
+	}
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
  * Write a word to Flash, returns:
  * 0 - OK
  * 1 - write timeout
@@ -520,8 +557,6 @@
 static int write_data (flash_info_t *info, ulong dest, ulong data)
 {
 	vu_long *addr = (vu_long *)dest;
-	ulong status;
-	ulong start;
 	int flag;
 
 	/* Check if Flash is (sufficiently) erased */
@@ -538,13 +573,8 @@
 	if (flag)
 		enable_interrupts();
 
-	start = get_timer (0);
-
-	while (((status = *addr) & 0x00800080) != 0x00800080) {
-		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
-			*addr = 0x00FF00FF;	/* restore read mode */
-			return (1);
-		}
+	if (flash_status_check(addr, CFG_FLASH_WRITE_TOUT, "write") != 0) {
+		return (1);
 	}
 
 	*addr = 0x00FF00FF;	/* restore read mode */
@@ -552,5 +582,46 @@
 	return (0);
 }
 
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+/*-----------------------------------------------------------------------
+ * Write a buffer to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ */
+static int write_data_buf(flash_info_t * info, ulong dest, uchar * cp, int len)
+{
+	vu_long *addr = (vu_long *)dest;
+	int sector;
+	int cnt;
+	int retcode;
+	vu_long * src = (vu_long *)cp;
+	vu_long * dst = (vu_long *)dest;
+
+	/* find sector */
+	for(sector = info->sector_count - 1; sector >= 0; sector--) {
+		if(dest >= info->start[sector])
+			break;
+	}
+
+	*addr = 0x00500050;		/* clear status */
+	*addr = 0x00e800e8;		/* write buffer */
+
+	if((retcode = flash_status_check(addr, CFG_FLASH_BUFFER_WRITE_TOUT,
+					 "write to buffer")) == 0) {
+		cnt = len / FLASH_WIDTH;
+		*addr = (cnt-1) | ((cnt-1) << 16);
+		while(cnt-- > 0) {
+			*dst++ = *src++;
+		}
+		*addr = 0x00d000d0;		/* write buffer confirm */
+		retcode = flash_status_check(addr, CFG_FLASH_BUFFER_WRITE_TOUT,
+						 "buffer write");
+	}
+	*addr = 0x00FF00FF;	/* restore read mode */
+	*addr = 0x00500050;	/* clear status */
+	return retcode;
+}
+#endif /* CFG_USE_FLASH_BUFFER_WRITE */
+
 /*-----------------------------------------------------------------------
  */