diff options
author | Scott Wood <scottwood@freescale.com> | 2013-03-02 08:50:33 (GMT) |
---|---|---|
committer | Fleming Andrew-AFLEMING <AFLEMING@freescale.com> | 2013-04-12 20:55:58 (GMT) |
commit | 4099f70e94789731c3a20f89be058cfb2bfed836 (patch) | |
tree | 25502a586adb334e22eb975a39109fd0282ce7e7 /arch/powerpc/kernel | |
parent | e2da5b69368bcae4fd1e121725a9b438c761f51c (diff) | |
download | linux-fsl-qoriq-4099f70e94789731c3a20f89be058cfb2bfed836.tar.xz |
powerpc/e500: work around erratum A-006184
Erratum A-006184 says that a hang can happen under certain
circumstances when taking an exception. The erratum workaround
gives the use of a watchdog as an option, to get unstuck if a hang
does occur.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Change-Id: Ib63bea70bb2ad7ea4cee9b96ec4f7aefc21ea3b3
Reviewed-on: http://git.am.freescale.net:8181/1113
Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/exceptions-64e.S | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_fsl_booke.S | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/idle.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 11 |
4 files changed, 32 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 39308c7..5e6a242 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -444,6 +444,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) fixed_interval, .unknown_exception, ACK_FIT) /* Watchdog Timer Interrupt */ +#ifdef CONFIG_FSL_ERRATUM_A_006184 + START_EXCEPTION(watchdog) + mtspr SPRN_SPRG_CRIT_SCRATCH, r3 + lis r3, TSR_WIS@h + mtspr SPRN_TSR, r3 + mfspr r3, SPRN_SPRG_CRIT_SCRATCH + rfci +#else START_EXCEPTION(watchdog); CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG, PROLOG_ADDITION_NONE) @@ -454,6 +462,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) // bl .unknown_exception // b ret_from_crit_except b . +#endif /* System Call Interrupt */ START_EXCEPTION(system_call) diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 58925b6..987a3f1 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -369,7 +369,15 @@ interrupt_base: unknown_exception, EXC_XFER_EE) /* Watchdog Timer Interrupt */ -#ifdef CONFIG_BOOKE_WDT +#ifdef CONFIG_FSL_ERRATUM_A_006184 + START_EXCEPTION(WatchdogTimer) + mtspr SPRN_SPRG_WSCRATCH_CRIT, r3 + lis r3, TSR_WIS@h + mtspr SPRN_TSR, r3 + /* use WSCRATCH to avoid any potential problems with KVM paravirt */ + mfspr r3, SPRN_SPRG_WSCRATCH_CRIT + rfci +#elif defined(CONFIG_BOOKE_WDT) CRITICAL_EXCEPTION(0x3200, WATCHDOG, WatchdogTimer, WatchdogException) #else CRITICAL_EXCEPTION(0x3200, WATCHDOG, WatchdogTimer, unknown_exception) diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index ea78761..c6ac64b 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -102,6 +102,9 @@ void cpu_idle(void) ppc64_runlatch_on(); rcu_idle_exit(); tick_nohz_idle_exit(); +#ifdef CONFIG_FSL_ERRATUM_A_006184 + mtspr(SPRN_TSR, TSR_ENW); +#endif if (cpu_should_die()) { sched_preempt_enable_no_resched(); cpu_die(); diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 127361e..9a9112f 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -488,6 +488,9 @@ void timer_interrupt(struct pt_regs * regs) struct clock_event_device *evt = &__get_cpu_var(decrementers); u64 now; +#ifdef CONFIG_FSL_ERRATUM_A_006184 + mtspr(SPRN_TSR, TSR_ENW); +#endif /* Ensure a positive value is written to the decrementer, or else * some CPUs will continue to take decrementer exceptions. */ @@ -638,7 +641,15 @@ void start_cpu_decrementer(void) mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); /* Enable decrementer interrupt */ +#ifdef CONFIG_FSL_ERRATUM_A_006184 +#define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15)) + { + u32 period = WDTP(CONFIG_FSL_ERRATUM_A_006184_PERIOD); + mtspr(SPRN_TCR, TCR_DIE | TCR_WIE | period); + } +#else mtspr(SPRN_TCR, TCR_DIE); +#endif #endif /* defined(CONFIG_BOOKE) || defined(CONFIG_40x) */ } |