summaryrefslogtreecommitdiff
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/lib/Kconfig9
-rw-r--r--arch/powerpc/lib/cache.c17
-rw-r--r--arch/powerpc/lib/interrupts.c2
4 files changed, 24 insertions, 5 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6a2e88fed25..133447648cc 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -49,5 +49,6 @@ source "arch/powerpc/cpu/mpc83xx/Kconfig"
source "arch/powerpc/cpu/mpc85xx/Kconfig"
source "arch/powerpc/cpu/mpc86xx/Kconfig"
source "arch/powerpc/cpu/mpc8xx/Kconfig"
+source "arch/powerpc/lib/Kconfig"
endmenu
diff --git a/arch/powerpc/lib/Kconfig b/arch/powerpc/lib/Kconfig
new file mode 100644
index 00000000000..b30b5edf7cf
--- /dev/null
+++ b/arch/powerpc/lib/Kconfig
@@ -0,0 +1,9 @@
+config CACHE_FLUSH_WATCHDOG_THRESHOLD
+ int "Bytes to flush between WATCHDOG_RESET calls"
+ default 0
+ help
+ The flush_cache() function periodically, and by default for
+ every cache line, calls WATCHDOG_RESET(). When flushing a
+ large area, that may add a significant amount of
+ overhead. This option allows you to set a threshold for how
+ many bytes to flush between each WATCHDOG_RESET call.
diff --git a/arch/powerpc/lib/cache.c b/arch/powerpc/lib/cache.c
index 3c3c470bbbd..19162511cea 100644
--- a/arch/powerpc/lib/cache.c
+++ b/arch/powerpc/lib/cache.c
@@ -9,10 +9,20 @@
#include <asm/cache.h>
#include <watchdog.h>
+static ulong maybe_watchdog_reset(ulong flushed)
+{
+ flushed += CONFIG_SYS_CACHELINE_SIZE;
+ if (flushed >= CONFIG_CACHE_FLUSH_WATCHDOG_THRESHOLD) {
+ WATCHDOG_RESET();
+ flushed = 0;
+ }
+ return flushed;
+}
+
void flush_cache(ulong start_addr, ulong size)
{
-#ifndef CONFIG_5xx
ulong addr, start, end;
+ ulong flushed = 0;
start = start_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
end = start_addr + size - 1;
@@ -20,7 +30,7 @@ void flush_cache(ulong start_addr, ulong size)
for (addr = start; (addr <= end) && (addr >= start);
addr += CONFIG_SYS_CACHELINE_SIZE) {
asm volatile("dcbst 0,%0" : : "r" (addr) : "memory");
- WATCHDOG_RESET();
+ flushed = maybe_watchdog_reset(flushed);
}
/* wait for all dcbst to complete on bus */
asm volatile("sync" : : : "memory");
@@ -28,10 +38,9 @@ void flush_cache(ulong start_addr, ulong size)
for (addr = start; (addr <= end) && (addr >= start);
addr += CONFIG_SYS_CACHELINE_SIZE) {
asm volatile("icbi 0,%0" : : "r" (addr) : "memory");
- WATCHDOG_RESET();
+ flushed = maybe_watchdog_reset(flushed);
}
asm volatile("sync" : : : "memory");
/* flush prefetch queue */
asm volatile("isync" : : : "memory");
-#endif
}
diff --git a/arch/powerpc/lib/interrupts.c b/arch/powerpc/lib/interrupts.c
index 73f270002cf..5ba4cd0c13a 100644
--- a/arch/powerpc/lib/interrupts.c
+++ b/arch/powerpc/lib/interrupts.c
@@ -80,7 +80,7 @@ void timer_interrupt(struct pt_regs *regs)
timestamp++;
#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
- if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
+ if (CONFIG_SYS_WATCHDOG_FREQ && (timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
WATCHDOG_RESET ();
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */