[U-Boot] [PATCH v2] arm: Kirkwood: add SYSRSTn Duration Counter Support

Prafulla Wadaskar prafulla at marvell.com
Fri Aug 7 18:33:02 CEST 2009


This feature can be used to trigger special command "sysrstcmd" using
reset key long press event and environment variable "sysrstdelay" is set
(useful for reset to factory or manufacturing mode execution)

Kirkwood SoC implements a hardware-based SYSRSTn duration counter.
When SYSRSTn is asserted low, a SYSRSTn duration counter is running.
The counter value is stored in the SYSRSTn Length Counter Register
The counter is based on the 25-MHz reference clock (40ns)
It is a 29-bit counter, yielding a maximum counting duration of
2^29/25 MHz (21.4 seconds). When the counter reach its maximum value,
it remains at this value until counter reset is triggered by setting
bit 31 of KW_REG_SYSRST_CNT

Implementation:
Upon long reset assertion (> ${sysrstdleay} in secs) sysrstcmd will be
executed if pre-defined in environment variables.
This feature will be disabled if "sysrstdelay" variable is unset.

for-ex.
setenv sysrst_cmd "echo starting factory reset;
		   nand erase 0xa0000 0x20000;
		   echo finish ed sysrst command;"
will erase particular nand sector if triggered by this event

Signed-off-by: Prafulla Wadaskar <prafulla at marvell.com>
---
Change log:
v2: command sysrst_cmd renamed as sysrstcmd
stsrstdelay variable added instead of hardcoding the value

 cpu/arm926ejs/kirkwood/cpu.c        |   79 +++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-kirkwood/cpu.h |    2 +
 2 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/cpu/arm926ejs/kirkwood/cpu.c b/cpu/arm926ejs/kirkwood/cpu.c
index 795a739..9a6ee57 100644
--- a/cpu/arm926ejs/kirkwood/cpu.c
+++ b/cpu/arm926ejs/kirkwood/cpu.c
@@ -195,6 +195,82 @@ int kw_config_mpp(u32 mpp0_7, u32 mpp8_15, u32 mpp16_23, u32 mpp24_31,
 	return 0;
 }
 
+/*
+ * SYSRSTn Duration Counter Support
+ *
+ * Kirkwood SoC implements a hardware-based SYSRSTn duration counter.
+ * When SYSRSTn is asserted low, a SYSRSTn duration counter is running.
+ * The SYSRSTn duration counter is useful for implementing a manufacturer
+ * or factory reset. Upon a long reset assertion that is greater than a
+ * pre-configured environment variable value for sysrstdelay,
+ * The counter value is stored in the SYSRSTn Length Counter Register
+ * The counter is based on the 25-MHz reference clock (40ns)
+ * It is a 29-bit counter, yielding a maximum counting duration of
+ * 2^29/25 MHz (21.4 seconds). When the counter reach its maximum value,
+ * it remains at this value until counter reset is triggered by setting
+ * bit 31 of KW_REG_SYSRST_CNT
+ */
+static void kw_sysrst_action(void)
+{
+#ifdef CONFIG_CMD_RUN
+	char cmd[BUFLEN];
+	char img[BUFLEN * 2];
+	char *argv[3];
+
+	if (getenv("sysrstcmd") == NULL) {
+		printf("Error.. %s failed, check sysrstcmd\n",
+			__FUNCTION__);
+		return;
+	}
+
+	printf("Starting %s process...\n", __FUNCTION__);
+	sprintf(cmd, "run ");
+	sprintf(img, "sysrstcmd");
+	argv[0] = cmd;
+	argv[1] = img;
+	if ((do_run(NULL, 0, 2, argv)) != 0x0) {
+		printf("Error.. %s failed\n", __FUNCTION__);
+	} else {
+		printf("%s process finished\n", __FUNCTION__);
+	}
+#else	/* CONFIG_CMD_RUN */
+	printf("Error.. %s needs run command support\n", __FUNCTION__);
+#endif	/* CONFIG_CMD_RUN */
+}
+
+static void kw_sysrst_check(void)
+{
+	u32 sysrst_cnt, sysrst_dly;
+	char *s;
+
+	/*
+	 * no action if sysrstdelay environment variable is not defined
+	 */
+	s = getenv("sysrstdelay");
+	if (s == NULL)
+		return;
+
+	/* read sysrstdelay value */
+	sysrst_dly = (u32) simple_strtoul(s, NULL, 10);
+
+	/* read SysRst Length counter register (bits 28:0) */
+	sysrst_cnt = (0x1fffffff & readl(KW_REG_SYSRST_CNT));
+	printf("H/w Rst hold time: %d.%d secs\n",
+		sysrst_cnt/SYSRST_CNT_1SEC_VAL,
+		sysrst_cnt%SYSRST_CNT_1SEC_VAL);
+
+	/* clear the counter for next valid read*/
+	writel(1 << 31, KW_REG_SYSRST_CNT);
+
+	/*
+	 * sysrst_action:
+	 * if H/w Reset key is pressed and hold for time
+	 * more than sysrst_dly in seconds
+	 */
+	if (sysrst_cnt >= SYSRST_CNT_1SEC_VAL * sysrst_dly)
+		kw_sysrst_action();
+}
+
 #if defined(CONFIG_DISPLAY_CPUINFO)
 int print_cpuinfo(void)
 {
@@ -298,6 +374,9 @@ int arch_misc_init(void)
 	temp = get_cr();
 	set_cr(temp & ~CR_V);
 
+	/* checks and execute resset to factory event */
+	kw_sysrst_check();
+
 	return 0;
 }
 #endif /* CONFIG_ARCH_MISC_INIT */
diff --git a/include/asm-arm/arch-kirkwood/cpu.h b/include/asm-arm/arch-kirkwood/cpu.h
index d1440af..b3022a3 100644
--- a/include/asm-arm/arch-kirkwood/cpu.h
+++ b/include/asm-arm/arch-kirkwood/cpu.h
@@ -36,6 +36,8 @@
 		((_x ? KW_EGIGA0_BASE : KW_EGIGA1_BASE) + 0x44c)
 
 #define KW_REG_DEVICE_ID		(KW_MPP_BASE + 0x34)
+#define KW_REG_SYSRST_CNT		(KW_MPP_BASE + 0x50)
+#define SYSRST_CNT_1SEC_VAL		(25*1000000)
 #define KW_REG_MPP_OUT_DRV_REG		(KW_MPP_BASE + 0xE0)
 
 enum memory_bank {
-- 
1.5.3.3



More information about the U-Boot mailing list