summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README9
-rw-r--r--arch/m68k/lib/time.c2
-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
-rw-r--r--drivers/timer/mpc83xx_timer.c6
-rw-r--r--drivers/watchdog/wdt-uclass.c2
8 files changed, 40 insertions, 8 deletions
diff --git a/README b/README
index a565748e43..ad13092bbb 100644
--- a/README
+++ b/README
@@ -747,6 +747,15 @@ The following options need to be configured:
SoC, then define this variable and provide board
specific code for the "hw_watchdog_reset" function.
+ CONFIG_SYS_WATCHDOG_FREQ
+ Some platforms automatically call WATCHDOG_RESET()
+ from the timer interrupt handler every
+ CONFIG_SYS_WATCHDOG_FREQ interrupts. If not set by the
+ board configuration file, a default of CONFIG_SYS_HZ/2
+ (i.e. 500) is used. Setting CONFIG_SYS_WATCHDOG_FREQ
+ to 0 disables calling WATCHDOG_RESET() from the timer
+ interrupt.
+
- Real-Time Clock:
When CONFIG_CMD_DATE is selected, the type of the RTC
diff --git a/arch/m68k/lib/time.c b/arch/m68k/lib/time.c
index cbe29e72a8..ebb2ac54db 100644
--- a/arch/m68k/lib/time.c
+++ b/arch/m68k/lib/time.c
@@ -71,7 +71,7 @@ void dtimer_interrupt(void *not_used)
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 */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6a2e88fed2..133447648c 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 0000000000..b30b5edf7c
--- /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 3c3c470bbb..19162511ce 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 73f270002c..5ba4cd0c13 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 */
diff --git a/drivers/timer/mpc83xx_timer.c b/drivers/timer/mpc83xx_timer.c
index f4f6e90387..952293195f 100644
--- a/drivers/timer/mpc83xx_timer.c
+++ b/drivers/timer/mpc83xx_timer.c
@@ -20,6 +20,10 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_SYS_WATCHDOG_FREQ
+#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
+#endif
+
/**
* struct mpc83xx_timer_priv - Private data structure for MPC83xx timer driver
* @decrementer_count: Value to which the decrementer register should be re-set
@@ -171,7 +175,7 @@ void timer_interrupt(struct pt_regs *regs)
priv->timestamp++;
#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
- if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
+ if (CONFIG_SYS_WATCHDOG_FREQ && (priv->timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
WATCHDOG_RESET();
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
index 0603ffbd36..2687135296 100644
--- a/drivers/watchdog/wdt-uclass.c
+++ b/drivers/watchdog/wdt-uclass.c
@@ -148,7 +148,7 @@ void watchdog_reset(void)
/* Do not reset the watchdog too often */
now = get_timer(0);
- if (time_after(now, next_reset)) {
+ if (time_after_eq(now, next_reset)) {
next_reset = now + reset_period;
wdt_reset(gd->watchdog_dev);
}