Merge remote-tracking branch 'gfiber-internal/prism_dev' into mergeprism2
diff --git a/board/mv_feroceon/USP/mv_spi.c b/board/mv_feroceon/USP/mv_spi.c
index 3d7da78..835d752 100644
--- a/board/mv_feroceon/USP/mv_spi.c
+++ b/board/mv_feroceon/USP/mv_spi.c
@@ -114,8 +114,8 @@
 	MV_STATUS ret;
 	MV_U8* pdout = (MV_U8*)dout;
 	MV_U8* pdin = (MV_U8*)din;
-	int tmp_bitlen = bitlen;
 #if 0
+	int tmp_bitlen = bitlen;
 	unsigned int tmpdout, tmpdin;
 	int tm, isread = 0;
 
@@ -161,6 +161,7 @@
 	/* Verify that the SPI mode is in 8bit mode */
 	MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG(0), MV_SPI_BYTE_LENGTH_MASK);
 
+#if 0
 	/* TX/RX in 8bit chanks */
 	
 	while (tmp_bitlen > 0)
@@ -179,6 +180,19 @@
 
 		tmp_bitlen-=8;
 	}
+#else
+	if (dout && din)
+		ret = mvSpiReadWrite(0, din, dout, (bitlen + 7) / 8);
+	else if (dout)
+		ret = mvSpiWrite(0, dout, (bitlen + 7) / 8);
+	else if (din)
+		ret = mvSpiRead(0, din, (bitlen + 7) / 8);
+	else
+		ret = MV_OK;
+
+	if (ret)
+		return ret;
+#endif
 
 #if 0
     }
diff --git a/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvLib.h b/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvLib.h
index d8b74cd..a7e75d7 100644
--- a/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvLib.h
+++ b/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvLib.h
@@ -403,6 +403,7 @@
 	char boardName[MV_BOARD_NAME_LEN];
 	MV_VOID (*pBoardEnvInit)(struct _boardInfo *);
 	MV_VOID (*pBoardEgigaPhyInit)(struct _boardInfo *);
+	MV_VOID (*pBoardPreBootOs)(struct _boardInfo *);
 	MV_U8 numBoardMppTypeValue;
 	MV_BOARD_MPP_TYPE_INFO *pBoardMppTypeValue;
 	MV_U8 numBoardMppConfigValue;
diff --git a/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvSpec.c b/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
index b86567f..ef83280 100644
--- a/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
+++ b/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
@@ -64,8 +64,12 @@
 #include "mvCommon.h"
 #include "mvBoardEnvLib.h"
 #include "mvBoardEnvSpec.h"
+#include "cntmr/mvCntmr.h"
 #include "eth-phy/mvEthPhy.h"
 #include "gpp/mvGpp.h"
+#include "spi_flash.h"
+#include "sys/mvCpuIf.h"
+#include "sysvar.h"
 #include "twsi/mvTwsi.h"
 
 /***************************************************************************
@@ -1317,10 +1321,25 @@
 	}
 }
 
+extern struct spi_flash *flash;
+
+static MV_VOID gflt200BoardPreBootOs(MV_BOARD_INFO *pBoardInfo)
+{
+	spi_flash_lock(flash, SYSVAR_RO_OFFSET0, SYSVAR_BLOCK_SIZE,
+			SPI_FLASH_LOCK_WRITE|SPI_FLASH_LOCK_DOWN);
+	spi_flash_lock(flash, SYSVAR_RO_OFFSET1, SYSVAR_BLOCK_SIZE,
+			SPI_FLASH_LOCK_WRITE|SPI_FLASH_LOCK_DOWN);
+
+	mvCpuIfEnableWatchdogReset();
+	mvCntmrWrite(WATCHDOG, 0xffffffff);
+	mvCntmrEnable(WATCHDOG);
+}
+
 MV_BOARD_INFO gflt200Info = {
 	.boardName = "GFLT200",
 	.pBoardEnvInit = gflt200BoardEnvInit,
 	.pBoardEgigaPhyInit = gflt200BoardEgigaPhyInit,
+	.pBoardPreBootOs = gflt200BoardPreBootOs,
 	.numBoardMppTypeValue = MV_ARRAY_SIZE(gflt200InfoBoardMppTypeInfo),
 	.pBoardMppTypeValue = gflt200InfoBoardMppTypeInfo,
 	.intsGppMaskLow = 0,
diff --git a/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvSpec.h b/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
index 2e1ce59..a237696 100644
--- a/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
+++ b/board/mv_feroceon/mv_kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
@@ -523,10 +523,10 @@
 #define GFLT200_EVT1_GPP_POL_LOW	0x0
 #define GFLT200_EVT1_GPP_POL_MID	0x0
 
-#define GFLT200_EVT2_GPP_OUT_ENA_LOW	(BIT9 | BIT13 | BIT15 | BIT18 | BIT27 | BIT29)
+#define GFLT200_EVT2_GPP_OUT_ENA_LOW	(BIT13 | BIT15 | BIT18 | BIT27 | BIT29)
 #define GFLT200_EVT2_GPP_OUT_ENA_MID	(BIT4)
 
-#define GFLT200_EVT2_GPP_OUT_VAL_LOW	(BIT21 | BIT28)
+#define GFLT200_EVT2_GPP_OUT_VAL_LOW	(BIT9 | BIT21 | BIT28)
 #define GFLT200_EVT2_GPP_OUT_VAL_MID	(BIT5)
 
 #define GFLT200_EVT2_GPP_POL_LOW	0x0
diff --git a/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/mvCtrlEnvSpec.h b/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/mvCtrlEnvSpec.h
index eed78d3..84a6f7c 100644
--- a/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/mvCtrlEnvSpec.h
+++ b/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/mvCtrlEnvSpec.h
@@ -135,7 +135,7 @@
 
 #define MV_GPP_MAX_PINS			96
 #define MV_GPP_MAX_GROUP    		3
-#define MV_CNTMR_MAX_COUNTER 		2
+#define MV_CNTMR_MAX_COUNTER 		3
 #define MV_UART_MAX_CHAN		2
 
 #define MV_XOR_6510_6530_MAX_UNIT	0
diff --git a/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/sys/mvCpuIf.c b/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/sys/mvCpuIf.c
index d9be3f2..7a8fb8d 100644
--- a/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/sys/mvCpuIf.c
+++ b/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/sys/mvCpuIf.c
@@ -890,3 +890,18 @@
 }
 
 #endif
+
+MV_VOID mvCpuIfEnableWatchdogReset(MV_VOID)
+{
+	MV_U32 val;
+
+	/* clear watchdog timer interrupt */
+	val = MV_REG_READ(CPU_AHB_MBUS_CAUSE_INT_REG);
+	val &= ~CAMCIR_ARM_WD_TIMER_INT_REQ;
+	MV_REG_WRITE(CPU_AHB_MBUS_CAUSE_INT_REG, val);
+
+	/* enable reset upon watchdog timer expiration */
+	val = MV_REG_READ(CPU_RSTOUTN_MASK_REG);
+	val |= CRMR_WD_RST_OUT_MASK;
+	MV_REG_WRITE(CPU_RSTOUTN_MASK_REG, val);
+}
diff --git a/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/sys/mvCpuIf.h b/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/sys/mvCpuIf.h
index 0df8f7d..2f2a2fe 100644
--- a/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/sys/mvCpuIf.h
+++ b/board/mv_feroceon/mv_kw2/kw2_family/ctrlEnv/sys/mvCpuIf.h
@@ -111,6 +111,7 @@
 MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin);
 
 MV_VOID mvCpuIfAddDecShow(MV_VOID);
+MV_VOID mvCpuIfEnableWatchdogReset(MV_VOID);
 
 #ifdef __cplusplus
 }
diff --git a/board/mv_feroceon/mv_kw2/mv_main.c b/board/mv_feroceon/mv_kw2/mv_main.c
index 75fb62c..f2dd23b 100644
--- a/board/mv_feroceon/mv_kw2/mv_main.c
+++ b/board/mv_feroceon/mv_kw2/mv_main.c
@@ -1476,3 +1476,11 @@
 	return pd->boot_mode;
 }
 #endif  /* CONFIG_POST || CONFIG_LOGBUFFER*/
+
+void board_pre_boot_os(void)
+{
+	MV_BOARD_INFO *pBoardInfo = mvBoardInfoGet();
+
+	if (pBoardInfo->pBoardPreBootOs)
+		pBoardInfo->pBoardPreBootOs(pBoardInfo);
+}
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index ea01393..ae835c0 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -166,6 +166,12 @@
 }
 void arch_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__arch_lmb_reserve")));
 
+void __board_pre_boot_os(void)
+{
+	/* please define platform specific board_pre_boot_os() */
+}
+void board_pre_boot_os(void) __attribute__((weak, alias("__board_pre_boot_os")));
+
 #if defined(__ARM__)
   #define IH_INITRD_ARCH IH_ARCH_ARM
 #elif defined(__avr32__)
@@ -673,6 +679,8 @@
 		return 1;
 	}
 
+	board_pre_boot_os();
+
 	boot_fn(0, argc, argv, &images);
 
 	show_boot_progress (-9);
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 5d7990b..4c8f542 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -177,6 +177,123 @@
 	puts("Usage: sf protect on/off\n");
 	return 1;
 }
+
+static int do_spi_flash_lock(int argc, char *argv[])
+{
+	int ret;
+	int lock;
+	char *endp;
+	unsigned long offset;
+
+	if (argc < 2)
+		goto usage;
+
+	offset = simple_strtoul(argv[1], &endp, 0);
+	if (*endp)
+		goto usage;
+
+	if (argc < 3)
+		ret = spi_flash_read_lock(flash, offset, &lock);
+	else {
+		if (!strcmp(argv[2], "off"))
+			lock = SPI_FLASH_LOCK_NONE;
+		else if (!strcmp(argv[2], "on"))
+			lock = SPI_FLASH_LOCK_WRITE;
+		else if (!strcmp(argv[2], "never"))
+			lock = SPI_FLASH_LOCK_DOWN;
+		else if (!strcmp(argv[2], "forever"))
+			lock = SPI_FLASH_LOCK_WRITE|SPI_FLASH_LOCK_DOWN;
+		else
+			goto usage;
+
+		ret = spi_flash_write_lock(flash, offset, lock);
+	}
+
+	if (ret) {
+		printf("SPI flash %s failed, error %d\n", argv[0], ret);
+		return 1;
+	}
+	else if (argc < 3) {
+		switch (lock) {
+		case SPI_FLASH_LOCK_NONE:
+			puts("off\n");
+			break;
+		case SPI_FLASH_LOCK_WRITE:
+			puts("on\n");
+			break;
+		case SPI_FLASH_LOCK_DOWN:
+			puts("never\n");
+			break;
+		case SPI_FLASH_LOCK_WRITE|SPI_FLASH_LOCK_DOWN:
+			puts("forever\n");
+			break;
+		default:
+			printf("? (%x)\n", lock);
+			break;
+		}
+	}
+
+	return 0;
+
+usage:
+	puts("Usage: sf lock offset [mode]\n"
+		" modes:\n"
+		"  'off' - unlocked\n"
+		"  'on' - locked\n"
+		"  'never' - unlock until power cycle\n"
+		"  'forever' - lock until power cycle\n");
+
+	return 1;
+}
+
+static int do_spi_flash_lock_range(int argc, char *argv[])
+{
+	int ret;
+	int lock;
+	char *endp;
+	unsigned long offset;
+	unsigned long len;
+
+	if (argc < 4)
+		goto usage;
+
+	offset = simple_strtoul(argv[1], &endp, 0);
+	if (*endp)
+		goto usage;
+
+	len = simple_strtoul(argv[2], &endp, 0);
+	if (*endp)
+		goto usage;
+
+	if (!strcmp(argv[3], "off"))
+		lock = SPI_FLASH_LOCK_NONE;
+	else if (!strcmp(argv[3], "on"))
+		lock = SPI_FLASH_LOCK_WRITE;
+	else if (!strcmp(argv[3], "never"))
+		lock = SPI_FLASH_LOCK_DOWN;
+	else if (!strcmp(argv[3], "forever"))
+		lock = SPI_FLASH_LOCK_WRITE|SPI_FLASH_LOCK_DOWN;
+	else
+		goto usage;
+
+	ret = spi_flash_lock(flash, offset, len, lock);
+	if (ret) {
+		printf("SPI flash %s failed, error %d\n", argv[0], ret);
+		return 1;
+	}
+
+	return 0;
+
+usage:
+	puts("Usage: sf lock-range offset len mode\n"
+		" modes:\n"
+		"  'off' - unlocked\n"
+		"  'on' - locked\n"
+		"  'never' - unlock until power cycle\n"
+		"  'forever' - lock until power cycle\n");
+
+	return 1;
+}
 #endif
 
 static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
@@ -205,6 +322,10 @@
 #ifdef CONFIG_SPI_FLASH_PROTECTION
 	if (strcmp(cmd, "protect") == 0)
 		return do_spi_flash_protect(argc - 1, argv + 1);
+	if (strcmp(cmd, "lock") == 0)
+		return do_spi_flash_lock(argc - 1, argv + 1);
+	if (strcmp(cmd, "lock-range") == 0)
+		return do_spi_flash_lock_range(argc - 1, argv + 1);
 #endif
 
 usage:
@@ -225,5 +346,7 @@
 #ifdef CONFIG_SPI_FLASH_PROTECTION
 	"sf protect on			- protect spi flash\n"
 	"sf protect off			- unprotect spi flash\n"
+	"sf lock offset [mode]		- get sector lock or set to `mode'\n"
+	"sf lock-range offset len mode	- set address range lock to `mode'\n"
 #endif
 );
diff --git a/common/cmd_sysvar.c b/common/cmd_sysvar.c
index 742da73..06e402e 100644
--- a/common/cmd_sysvar.c
+++ b/common/cmd_sysvar.c
@@ -57,6 +57,15 @@
 
     /* check crc32 and wc32 (write count) */
     if (check_var(buf, SYSVAR_LOAD_MODE) == SYSVAR_SUCCESS) {
+#ifdef CONFIG_SPI_FLASH_PROTECTION
+      printf("SV: Unprotecting flash\n");
+      ret = spi_flash_protect(sf_dev, 0);
+      if (ret) {
+        printf("## Error: failed to unprotect flash\n");
+        goto recovery_err;
+      }
+#endif
+
       /* erase SPI flash */
       ret = spi_flash_erase(sf_dev, sysvar_offset[j], buf->data_len);
       if (ret) {
@@ -77,6 +86,13 @@
         goto recovery_err;
       }
 
+#ifdef CONFIG_SPI_FLASH_PROTECTION
+     printf("SV: Protecting flash\n");
+     ret = spi_flash_protect(sf_dev, 1);
+     if (ret)
+       printf("## Error: failed to protect flash\n");
+#endif
+
       buf->loaded = true;
       print_msg("Data recovery was completed", SYSVAR_MESSAGE);
       return 0;
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
index 3f814de..985880a 100644
--- a/drivers/mtd/spi/stmicro.c
+++ b/drivers/mtd/spi/stmicro.c
@@ -46,6 +46,8 @@
 #define CMD_M25PXX_DP		0xb9	/* Deep Power-down */
 #define CMD_M25PXX_RES		0xab	/* Release from DP, and Read Signature */
 #define CMD_M25PXX_EN4BYTEADDR	0xb7	/* Enter 4-byte address mode */
+#define CMD_M25PXX_RDLR		0xe8	/* Read Lock Register */
+#define CMD_M25PXX_WRLR		0xe5	/* Write Lock Register */
 
 #define STM_ID_M25P16		0x15
 #define STM_ID_M25P20		0x12
@@ -198,6 +200,29 @@
 	return -1;
 }
 
+static u8 *stmicro_set_cmd_addr(struct stmicro_spi_flash *stm, u8 *cmd,
+				u32 addr)
+{
+	unsigned long page_addr = addr / stm->params->page_size;
+
+	switch  (stm->params->addr_cycles) {
+	case 4:
+		*cmd++ = page_addr >> 16;
+		*cmd++ = page_addr >> 8;
+		*cmd++ = page_addr;
+		*cmd++ = addr % stm->params->page_size;
+		break;
+	case 3:
+	default:
+		*cmd++ = page_addr >> 8;
+		*cmd++ = page_addr;
+		*cmd++ = addr % stm->params->page_size;
+		break;
+	}
+
+	return cmd;
+}
+
 static int stmicro_read_fast(struct spi_flash *flash,
 			     u32 offset, size_t len, void *buf)
 {
@@ -431,6 +456,88 @@
 	spi_release_bus(flash->spi);
 	return ret;
 }
+
+static int stmicro_read_lock(struct spi_flash *flash, u32 offset, int *lock)
+{
+	u8 cmd[5];
+	u8 data;
+	int ret;
+	struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+
+	ret = spi_claim_bus(flash->spi);
+	if (ret)
+		return ret;
+
+	cmd[0] = CMD_M25PXX_RDLR;
+	stmicro_set_cmd_addr(stm, &cmd[1], offset);
+	ret = spi_flash_cmd_read(flash->spi, cmd, 1 + stm->params->addr_cycles,
+					&data, 1);
+	if (ret < 0) {
+		debug("SF: STMicro Read Lock register failed\n");
+		return ret;
+	}
+
+	spi_release_bus(flash->spi);
+	*lock = data;
+
+	return 0;
+}
+
+static int stmicro_write_lock(struct spi_flash *flash, u32 offset, int lock)
+{
+	u8 cmd[5];
+	u8 data = lock;
+	int ret;
+	struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+
+	ret = spi_claim_bus(flash->spi);
+	if (ret)
+		return ret;
+
+	ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0);
+	if (ret < 0) {
+		debug("SF: Write Enable failed\n");
+		return ret;
+	}
+
+	cmd[0] = CMD_M25PXX_WRLR;
+	stmicro_set_cmd_addr(stm, &cmd[1], offset);
+	ret = spi_flash_cmd_write(flash->spi, cmd, 1 + stm->params->addr_cycles,
+					&data, 1);
+	if (ret < 0) {
+		debug("SF: STMicro Write Lock register failed\n");
+		return ret;
+	}
+
+	spi_release_bus(flash->spi);
+
+	return 0;
+}
+
+static int stmicro_lock(struct spi_flash *flash, u32 offset, size_t len,
+			int lock)
+{
+	int ret;
+	u32 cur;
+	u32 end;
+	u32 sector_size;
+	struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+
+	sector_size
+		= (u32)stm->params->page_size * stm->params->pages_per_sector;
+	cur = (offset / sector_size) * sector_size;
+	end = offset + len;
+
+	while (cur < end) {
+		ret = stmicro_write_lock(flash, cur, lock);
+		if (ret)
+			return ret;
+
+		cur += sector_size;
+	}
+
+	return 0;
+}
 #endif
 
 struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
@@ -466,6 +573,9 @@
 	stm->flash.read = stmicro_read_fast;
 #ifdef CONFIG_SPI_FLASH_PROTECTION
 	stm->flash.protect = stmicro_protect;
+	stm->flash.read_lock = stmicro_read_lock;
+	stm->flash.write_lock = stmicro_write_lock;
+	stm->flash.lock = stmicro_lock;
 #endif
 	stm->flash.size = params->page_size * params->pages_per_sector
 	    * params->nr_sectors;
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 935ad5d..76ba799 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -23,8 +23,13 @@
 #ifndef _SPI_FLASH_H_
 #define _SPI_FLASH_H_
 
+#include <asm/errno.h>
 #include <spi.h>
 
+#define SPI_FLASH_LOCK_NONE	0x00
+#define SPI_FLASH_LOCK_WRITE	0x01	/* disable sector erase/program */
+#define SPI_FLASH_LOCK_DOWN	0x02	/* disable lock modification */
+
 struct spi_flash_region {
 	unsigned int	count;
 	unsigned int	size;
@@ -45,6 +50,12 @@
 				size_t len);
 #ifdef CONFIG_SPI_FLASH_PROTECTION
 	int		(*protect)(struct spi_flash *flash, int enable);
+	int		(*read_lock)(struct spi_flash *flash, u32 offset,
+					int *lock);
+	int		(*write_lock)(struct spi_flash *flash, u32 offset,
+					int lock);
+	int		(*lock)(struct spi_flash *flash, u32 offset, size_t len,
+				int lock);
 #endif
 };
 
@@ -74,5 +85,32 @@
 {
 	return flash->protect(flash, enable);
 }
+
+static inline int spi_flash_read_lock(struct spi_flash *flash, u32 offset,
+					int *lock)
+{
+	if (flash->read_lock)
+		return flash->read_lock(flash, offset, lock);
+
+	return -ENOSYS;
+}
+
+static inline int spi_flash_write_lock(struct spi_flash *flash, u32 offset,
+					int lock)
+{
+	if (flash->write_lock)
+		return flash->write_lock(flash, offset, lock);
+
+	return -ENOSYS;
+}
+
+static inline int spi_flash_lock(struct spi_flash *flash, u32 offset,
+					size_t len, int lock)
+{
+	if (flash->lock)
+		return flash->lock(flash, offset, len, lock);
+
+	return -ENOSYS;
+}
 #endif
 #endif /* _SPI_FLASH_H_ */