diff options
| -rw-r--r-- | cpu/arm926ejs/kirkwood/cpu.c | 75 | ||||
| -rw-r--r-- | include/asm-arm/arch-kirkwood/cpu.h | 2 | 
2 files changed, 77 insertions, 0 deletions
| diff --git a/cpu/arm926ejs/kirkwood/cpu.c b/cpu/arm926ejs/kirkwood/cpu.c index 795a73902..bab5faf65 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 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) +{ +	int ret; +	char *s = getenv("sysrstcmd"); + +	if (!s) { +		debug("Error.. %s failed, check sysrstcmd\n", +			__FUNCTION__); +		return; +	} + +	debug("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 +	if (ret < 0) +		debug("Error.. %s failed\n", __FUNCTION__); +	else +		debug("%s process finished\n", __FUNCTION__); +} + +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)); +	debug("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 +370,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 d1440af4b..b3022a378 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 { |