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

This feature can be used to trigger special command "sysrst_cmd" using reset key long press event (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 SYSRSTn duration counter is useful for implementing a sysrst_cmd. Upon a long reset assertion that is greater than a pre-configured threshold CONFIG_SYS_RST_THRESHOLD_TIME, 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 (> 5secs) sysrst_cmd will be executed if pre-defined in environment variables
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@marvell.com --- cpu/arm926ejs/kirkwood/cpu.c | 77 +++++++++++++++++++++++++++++++++++ include/asm-arm/arch-kirkwood/cpu.h | 2 + 2 files changed, 79 insertions(+), 0 deletions(-)
diff --git a/cpu/arm926ejs/kirkwood/cpu.c b/cpu/arm926ejs/kirkwood/cpu.c index 795a739..a23c61f 100644 --- a/cpu/arm926ejs/kirkwood/cpu.c +++ b/cpu/arm926ejs/kirkwood/cpu.c @@ -195,6 +195,78 @@ 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 threshold CONFIG_SYS_RST_THRESHOLD_TIME, + * 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 + */ +#ifndef CONFIG_SYS_RST_THRESHOLD_TIME +#define CONFIG_SYS_RST_THRESHOLD_TIME 5 +#endif /* CONFIG_SYS_RST_THRESHOLD_TIME */ +static void kw_sysrst_action(void) +{ +#ifdef CONFIG_CMD_RUN + char cmd[BUFLEN]; + char img[BUFLEN * 2]; + char *argv[3]; + + printf("Starting %s process...\n", __FUNCTION__); + sprintf(cmd, "run "); + sprintf(img, "sysrst_cmd"); + 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 = 0; + + /* 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); + + /* + * no action if read count value is less than + * CONFIG_SYS_RST_THRESHOLD_TIME in seconds + */ + if (sysrst_cnt < SYSRST_CNT_1SEC_VAL * CONFIG_SYS_RST_THRESHOLD_TIME) + return; + + /* + * sysrst_action: + * if H/w Reset key is pressed and hold for time + * more than CONFIG_SYS_RST_THRESHOLD_TIME seconds + */ + if (getenv("sysrst_cmd") == NULL) { + printf("Error.. %s failed, check sysrst_cmd\n", + __FUNCTION__); + return; + } else + kw_sysrst_action(); +} + #if defined(CONFIG_DISPLAY_CPUINFO) int print_cpuinfo(void) { @@ -298,6 +370,11 @@ int arch_misc_init(void) temp = get_cr(); set_cr(temp & ~CR_V);
+#ifdef CONFIG_SYS_TIME_RST2FACTORY + /* checks and execute resset to factory event */ + kw_sysrst_check(); +#endif /* CONFIG_SYS_TIME_RST2FACTORY */ + 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 {

Dear Prafulla Wadaskar,
In message 1249583526-22532-1-git-send-email-prafulla@marvell.com you wrote:
This feature can be used to trigger special command "sysrst_cmd" using reset key long press event (useful for reset to factory or manufacturing mode execution)
Cool.
Implementation: upon long reset assertion (> 5secs) sysrst_cmd will be executed if pre-defined in environment variables
I like the feature, but I don't like the hardwired timeout value.
+#ifndef CONFIG_SYS_RST_THRESHOLD_TIME +#define CONFIG_SYS_RST_THRESHOLD_TIME 5 +#endif /* CONFIG_SYS_RST_THRESHOLD_TIME */
Could you please use an environment variable for this, i. e. "sysrstcmd" and "sysrstdelay" (note that I omitted the underscore, too, because it looks ugly to me). This goes more in line with existing definitions like "bootcmd" and "bootdelay".
Thanks.
Best regards,
Wolfgang Denk

-----Original Message----- From: Wolfgang Denk [mailto:wd@denx.de] Sent: Thursday, August 06, 2009 7:53 PM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Prabhanjan Sarnaik Subject: Re: [U-Boot] [PATCH] arm: Kirkwood: add SYSRSTn Duration Counter Support
Dear Prafulla Wadaskar,
In message 1249583526-22532-1-git-send-email-prafulla@marvell.com you wrote:
This feature can be used to trigger special command
"sysrst_cmd" using
reset key long press event (useful for reset to factory or manufacturing mode execution)
Cool.
Implementation: upon long reset assertion (> 5secs)
sysrst_cmd will be
executed if pre-defined in environment variables
I like the feature, but I don't like the hardwired timeout value.
+#ifndef CONFIG_SYS_RST_THRESHOLD_TIME +#define CONFIG_SYS_RST_THRESHOLD_TIME 5 +#endif /* CONFIG_SYS_RST_THRESHOLD_TIME */
Could you please use an environment variable for this, i. e. "sysrstcmd" and "sysrstdelay" (note that I omitted the underscore, too, because it looks ugly to me). This goes more in line with existing definitions like "bootcmd" and "bootdelay".
This was in my mind too, the changes are ready, thanks for suggesting better names for environment variables. I will post v2 for the same
Regards... Prafulla . .
Thanks.
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de Your csh still thinks true is false. Write to your vendor today and tell them that next year Configure ought to "rm /bin/csh" unless they fix their blasted shell. :-) - Larry Wall in Configure from the perl distribution

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@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 {

On 22:03 Fri 07 Aug , Prafulla Wadaskar wrote:
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@marvell.com
a readme would be nice and maybe make it more generic so other soc could also implement it
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 */
why not replace this by
char *s = getenv("sysrstcmd");
if (!s) { printf("Error.. %s failed, check sysrstcmd\n", __FUNCTION__); return; }
printf("Starting %s process...\n", __FUNCTION__); #if !defined(CONFIG_SYS_HUSH_PARSER) ret = run_command (s, 0); #else ret = parse_string_outer(s, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); #endif ...
+}
+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);
please add space before and after %/ etc..
- /* 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();
+}
Best Regards, J.

Dear Jean-Christophe PLAGNIOL-VILLARD,
In message 20090817221152.GM23695@game.jcrosoft.org you wrote:
- 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 */
why not replace this by
char *s = getenv("sysrstcmd");
if (!s) { printf("Error.. %s failed, check sysrstcmd\n", __FUNCTION__); return; }
printf("Starting %s process...\n", __FUNCTION__); #if !defined(CONFIG_SYS_HUSH_PARSER) ret = run_command (s, 0); #else ret = parse_string_outer(s, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); #endif
Maybe because the original code does not need an #ifdef ?
Best regards,
Wolfgang Denk

On 00:36 Tue 18 Aug , Wolfgang Denk wrote:
Dear Jean-Christophe PLAGNIOL-VILLARD,
In message 20090817221152.GM23695@game.jcrosoft.org you wrote:
- 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 */
why not replace this by
char *s = getenv("sysrstcmd");
if (!s) { printf("Error.. %s failed, check sysrstcmd\n", __FUNCTION__); return; }
printf("Starting %s process...\n", __FUNCTION__); #if !defined(CONFIG_SYS_HUSH_PARSER) ret = run_command (s, 0); #else ret = parse_string_outer(s, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); #endif
Maybe because the original code does not need an #ifdef ?
but the size is bigger on the current implementation and as we have this is other part of U-Boot we can add a inline to have the ifdef at only one place
Best Regards, J.

-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Tuesday, August 18, 2009 4:24 AM To: Wolfgang Denk Cc: Prafulla Wadaskar; u-boot@lists.denx.de; Ashish Karkare; Prabhanjan Sarnaik Subject: Re: [U-Boot] [PATCH v2] arm: Kirkwood: add SYSRSTn Duration Counter Support
On 00:36 Tue 18 Aug , Wolfgang Denk wrote:
Dear Jean-Christophe PLAGNIOL-VILLARD,
In message 20090817221152.GM23695@game.jcrosoft.org you wrote:
- 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 */
I think better approach will be report it at build time i.e. #error "Error.. CONFIG_CMD_RUN needed for sysrstcmd support"
- printf("Error.. %s needs run command
support\n", __FUNCTION__);
+#endif /* CONFIG_CMD_RUN */
why not replace this by
char *s = getenv("sysrstcmd");
if (!s) { printf("Error.. %s failed, check sysrstcmd\n", __FUNCTION__); return; }
printf("Starting %s process...\n", __FUNCTION__); #if !defined(CONFIG_SYS_HUSH_PARSER) ret = run_command (s, 0); #else ret = parse_string_outer(s, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
I had checked this before, this is already done in the context of do_run to avoid code duplication I have used do_run.
#endif
Maybe because the original code does not need an #ifdef ?
but the size is bigger on the current implementation and as we have this is other part of U-Boot we can add a inline to have the ifdef at only one place
As suggested above, we can report it at build time and reduce some on binary size too.
Regards.. Prafulla . .
Best Regards, J.
participants (3)
-
Jean-Christophe PLAGNIOL-VILLARD
-
Prafulla Wadaskar
-
Wolfgang Denk