summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2013-03-02 08:50:33 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-04-12 20:55:58 (GMT)
commit4099f70e94789731c3a20f89be058cfb2bfed836 (patch)
tree25502a586adb334e22eb975a39109fd0282ce7e7 /arch/powerpc/kernel
parente2da5b69368bcae4fd1e121725a9b438c761f51c (diff)
downloadlinux-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.S9
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S10
-rw-r--r--arch/powerpc/kernel/idle.c3
-rw-r--r--arch/powerpc/kernel/time.c11
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) */
}