summaryrefslogtreecommitdiffstats
path: root/target/linux
diff options
context:
space:
mode:
authorkaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>2011-07-08 09:33:13 +0000
committerkaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>2011-07-08 09:33:13 +0000
commit53512ff331622136d97f60427f976473e549d28e (patch)
tree431b8960a1afd696ac9a51a18c735bcc610e9bb7 /target/linux
parent10e2f68dfd2dea1dc6e0f64f6e54869bb445f8db (diff)
[generic/3.0]: add mpcore_wdt fixes
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@27557 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux')
-rw-r--r--target/linux/generic/patches-3.0/991-arm_smp_twd_fix_typo.patch28
-rw-r--r--target/linux/generic/patches-3.0/992-mpcore_wdt_fix_watchdog_counter_loading.patch64
-rw-r--r--target/linux/generic/patches-3.0/993-mpcore_wdt_fix_wdioc_setoptions_handling.patch29
-rw-r--r--target/linux/generic/patches-3.0/994-mpcore_wdt_fix_timer_mode_setup.patch57
4 files changed, 178 insertions, 0 deletions
diff --git a/target/linux/generic/patches-3.0/991-arm_smp_twd_fix_typo.patch b/target/linux/generic/patches-3.0/991-arm_smp_twd_fix_typo.patch
new file mode 100644
index 000000000..957475727
--- /dev/null
+++ b/target/linux/generic/patches-3.0/991-arm_smp_twd_fix_typo.patch
@@ -0,0 +1,28 @@
+To get hundredths of MHz the rate needs to be divided by 10'000.
+Here is an example:
+ twd_timer_rate = 123456789
+ Before the patch:
+ twd_timer_rate / 1000000 = 123
+ (twd_timer_rate / 1000000) % 100 = 23
+ Result: 123.23MHz.
+ After being fixed:
+ twd_timer_rate / 1000000 = 123
+ (twd_timer_rate / 10000) % 100 = 45
+ Result: 123.45MHz.
+
+Signed-off-by: Vitaly Kuzmichev <vkuzmichev@mvista.com>
+---
+ arch/arm/kernel/smp_twd.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/arch/arm/kernel/smp_twd.c
++++ b/arch/arm/kernel/smp_twd.c
+@@ -115,7 +115,7 @@ static void __cpuinit twd_calibrate_rate
+ twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
+
+ printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
+- (twd_timer_rate / 1000000) % 100);
++ (twd_timer_rate / 10000) % 100);
+ }
+ }
+
diff --git a/target/linux/generic/patches-3.0/992-mpcore_wdt_fix_watchdog_counter_loading.patch b/target/linux/generic/patches-3.0/992-mpcore_wdt_fix_watchdog_counter_loading.patch
new file mode 100644
index 000000000..87c1c02ba
--- /dev/null
+++ b/target/linux/generic/patches-3.0/992-mpcore_wdt_fix_watchdog_counter_loading.patch
@@ -0,0 +1,64 @@
+Although the commit "98af057092f8f0dabe63c5df08adc2bbfbddb1d2
+ ARM: 6126/1: ARM mpcore_wdt: fix build failure and other fixes"
+resolved long standing mpcore_wdt driver build problems, it
+introduced an error in the relationship between the MPcore watchdog
+timer clock rate and mpcore_margin, "MPcore timer margin in seconds",
+such that watchdog timeouts are now arbitrary rather than the number
+of seconds specified by mpcore_margin.
+
+This change restores mpcore_wdt_keepalive() to its equivalent
+implementation prior to commit 98af057 such that watchdog timeouts now
+occur as specified by mpcore_margin.
+
+The variable 'mpcore_timer_rate' which caused that build failure was
+replaced by 'twd_timer_rate'. Adding exported function to obtain
+'twd_timer_rate' value in mpcore_wdt driver.
+
+MPCORE_WATCHDOG needed to build 'mpcore_wdt' already depends on
+HAVE_ARM_TWD needed to build 'smp_twd', so from the point of view of
+'mpcore_wdt' driver the exported function will always exist.
+
+Signed-off-by: Valentine Barshak <vbarshak@mvista.com>
+Signed-off-by: Vitaly Kuzmichev <vkuzmichev@mvista.com>
+---
+
+ arch/arm/include/asm/smp_twd.h | 1 +
+ arch/arm/kernel/smp_twd.c | 7 +++++++
+ drivers/watchdog/mpcore_wdt.c | 4 +---
+ 3 files changed, 9 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/include/asm/smp_twd.h
++++ b/arch/arm/include/asm/smp_twd.h
+@@ -24,5 +24,6 @@ extern void __iomem *twd_base;
+
+ int twd_timer_ack(void);
+ void twd_timer_setup(struct clock_event_device *);
++unsigned long twd_timer_get_rate(void);
+
+ #endif
+--- a/arch/arm/kernel/smp_twd.c
++++ b/arch/arm/kernel/smp_twd.c
+@@ -142,3 +142,10 @@ void __cpuinit twd_timer_setup(struct cl
+
+ clockevents_register_device(clk);
+ }
++
++/* Needed by mpcore_wdt */
++unsigned long twd_timer_get_rate(void)
++{
++ return twd_timer_rate;
++}
++EXPORT_SYMBOL_GPL(twd_timer_get_rate);
+--- a/drivers/watchdog/mpcore_wdt.c
++++ b/drivers/watchdog/mpcore_wdt.c
+@@ -99,9 +99,7 @@ static void mpcore_wdt_keepalive(struct
+
+ spin_lock(&wdt_lock);
+ /* Assume prescale is set to 256 */
+- count = __raw_readl(wdt->base + TWD_WDOG_COUNTER);
+- count = (0xFFFFFFFFU - count) * (HZ / 5);
+- count = (count / 256) * mpcore_margin;
++ count = (twd_timer_get_rate() / 256) * mpcore_margin;
+
+ /* Reload the counter */
+ writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
diff --git a/target/linux/generic/patches-3.0/993-mpcore_wdt_fix_wdioc_setoptions_handling.patch b/target/linux/generic/patches-3.0/993-mpcore_wdt_fix_wdioc_setoptions_handling.patch
new file mode 100644
index 000000000..fa261ce64
--- /dev/null
+++ b/target/linux/generic/patches-3.0/993-mpcore_wdt_fix_wdioc_setoptions_handling.patch
@@ -0,0 +1,29 @@
+According to the include/linux/watchdog.h WDIOC_SETOPTIONS is
+classified as 'read from device' ioctl call:
+ #define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int)
+
+However, the driver 'mpcore_wdt' performs 'copy_from_user' only if
+_IOC_WRITE is set, thus the local variable 'uarg' which is used in
+WDIOC_SETOPTIONS handling remains uninitialized.
+
+The proper way to fix this is to bind WDIOC_SETOPTIONS to _IOW,
+but this will break compatibility.
+So adding additional condition for performing 'copy_from_user'.
+
+Signed-off-by: Vitaly Kuzmichev <vkuzmichev@mvista.com>
+---
+ drivers/watchdog/mpcore_wdt.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+--- a/drivers/watchdog/mpcore_wdt.c
++++ b/drivers/watchdog/mpcore_wdt.c
+@@ -233,7 +233,8 @@ static long mpcore_wdt_ioctl(struct file
+ if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
+ return -ENOTTY;
+
+- if (_IOC_DIR(cmd) & _IOC_WRITE) {
++ if ((_IOC_DIR(cmd) & _IOC_WRITE)
++ || cmd == WDIOC_SETOPTIONS) {
+ ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
+ if (ret)
+ return -EFAULT;
diff --git a/target/linux/generic/patches-3.0/994-mpcore_wdt_fix_timer_mode_setup.patch b/target/linux/generic/patches-3.0/994-mpcore_wdt_fix_timer_mode_setup.patch
new file mode 100644
index 000000000..009092376
--- /dev/null
+++ b/target/linux/generic/patches-3.0/994-mpcore_wdt_fix_timer_mode_setup.patch
@@ -0,0 +1,57 @@
+Allow watchdog to set its iterrupt as pending when it is configured
+for timer mode (in other words, allow emitting interrupt).
+Also add macros for all Watchdog Control Register flags.
+
+Signed-off-by: Vitaly Kuzmichev <vkuzmichev@mvista.com>
+---
+ arch/arm/include/asm/smp_twd.h | 6 ++++++
+ drivers/watchdog/mpcore_wdt.c | 15 +++++++++++----
+ 2 files changed, 17 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/include/asm/smp_twd.h
++++ b/arch/arm/include/asm/smp_twd.h
+@@ -18,6 +18,12 @@
+ #define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
+ #define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
+
++#define TWD_WDOG_CONTROL_ENABLE (1 << 0)
++#define TWD_WDOG_CONTROL_PERIODIC (1 << 1)
++#define TWD_WDOG_CONTROL_IT_ENABLE (1 << 2)
++#define TWD_WDOG_CONTROL_TIMER_MODE (0 << 3)
++#define TWD_WDOG_CONTROL_WATCHDOG_MODE (1 << 3)
++
+ struct clock_event_device;
+
+ extern void __iomem *twd_base;
+--- a/drivers/watchdog/mpcore_wdt.c
++++ b/drivers/watchdog/mpcore_wdt.c
+@@ -118,18 +118,25 @@ static void mpcore_wdt_stop(struct mpcor
+
+ static void mpcore_wdt_start(struct mpcore_wdt *wdt)
+ {
++ u32 mode;
++
+ dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
+
+ /* This loads the count register but does NOT start the count yet */
+ mpcore_wdt_keepalive(wdt);
+
++ /* Setup watchdog - prescale=256, enable=1 */
++ mode = (255 << 8) | TWD_WDOG_CONTROL_ENABLE;
++
+ if (mpcore_noboot) {
+- /* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
+- writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
++ /* timer mode, send interrupt */
++ mode |= TWD_WDOG_CONTROL_TIMER_MODE |
++ TWD_WDOG_CONTROL_IT_ENABLE;
+ } else {
+- /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
+- writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
++ /* watchdog mode */
++ mode |= TWD_WDOG_CONTROL_WATCHDOG_MODE;
+ }
++ writel(mode, wdt->base + TWD_WDOG_CONTROL);
+ }
+
+ static int mpcore_wdt_set_heartbeat(int t)