diff options
author | Koen Vandeputte <koen.vandeputte@ncentric.com> | 2018-01-11 16:04:34 +0100 |
---|---|---|
committer | John Crispin <john@phrozen.org> | 2018-01-17 11:07:17 +0100 |
commit | 0ef702c7e3866755659447c36a8e24c210be5aeb (patch) | |
tree | bb6642603696e485f1b94f03db27549b47d7c820 /target/linux/cns3xxx/patches-4.14/020-watchdog_support.patch | |
parent | 809a265e35bb1ee8fc4c2d1b14dee7cc945bb1b3 (diff) | |
download | upstream-0ef702c7e3866755659447c36a8e24c210be5aeb.tar.gz upstream-0ef702c7e3866755659447c36a8e24c210be5aeb.tar.bz2 upstream-0ef702c7e3866755659447c36a8e24c210be5aeb.zip |
cns3xxx: copy patches for kernel 4.14
Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
Diffstat (limited to 'target/linux/cns3xxx/patches-4.14/020-watchdog_support.patch')
-rw-r--r-- | target/linux/cns3xxx/patches-4.14/020-watchdog_support.patch | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/target/linux/cns3xxx/patches-4.14/020-watchdog_support.patch b/target/linux/cns3xxx/patches-4.14/020-watchdog_support.patch new file mode 100644 index 0000000000..4f9f3e6465 --- /dev/null +++ b/target/linux/cns3xxx/patches-4.14/020-watchdog_support.patch @@ -0,0 +1,185 @@ +Add a watchdog driver for ARM MPcore processors. + +Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -324,6 +324,13 @@ config KS8695_WATCHDOG + Watchdog timer embedded into KS8695 processor. This will reboot your + system when the timeout is reached. + ++config MPCORE_WATCHDOG ++ tristate "MPcore watchdog" ++ depends on HAVE_ARM_TWD ++ select WATCHDOG_CORE ++ help ++ Watchdog timer embedded into the MPcore system ++ + config HAVE_S3C2410_WATCHDOG + bool + help +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -47,6 +47,7 @@ obj-$(CONFIG_21285_WATCHDOG) += wdt285.o + obj-$(CONFIG_977_WATCHDOG) += wdt977.o + obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o + obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o ++obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o + obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o + obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o + obj-$(CONFIG_SAMA5D4_WATCHDOG) += sama5d4_wdt.o +--- /dev/null ++++ b/drivers/watchdog/mpcore_wdt.c +@@ -0,0 +1,118 @@ ++/* ++ * Watchdog driver for ARM MPcore ++ * ++ * Copyright (C) 2017 Felix Fietkau <nbd@nbd.name> ++ */ ++ ++#include <linux/export.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/watchdog.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++#include <asm/smp_twd.h> ++ ++static void __iomem *wdt_base; ++static int wdt_timeout = 60; ++ ++static int mpcore_wdt_keepalive(struct watchdog_device *wdd) ++{ ++ static int perturb; ++ u32 count; ++ ++ count = (twd_timer_get_rate() / 256) * wdt_timeout; ++ ++ /* Reload register needs a different value on each refresh */ ++ count += perturb; ++ perturb = !perturb; ++ ++ iowrite32(count, wdt_base + TWD_WDOG_LOAD); ++ ++ return 0; ++} ++ ++static int mpcore_wdt_start(struct watchdog_device *wdd) ++{ ++ mpcore_wdt_keepalive(wdd); ++ ++ /* prescale = 256, mode = 1, enable = 1 */ ++ iowrite32(0x0000FF09, wdt_base + TWD_WDOG_CONTROL); ++ ++ return 0; ++} ++ ++static int mpcore_wdt_stop(struct watchdog_device *wdd) ++{ ++ iowrite32(0x12345678, wdt_base + TWD_WDOG_DISABLE); ++ iowrite32(0x87654321, wdt_base + TWD_WDOG_DISABLE); ++ iowrite32(0x0, wdt_base + TWD_WDOG_CONTROL); ++ ++ return 0; ++} ++ ++static int mpcore_wdt_set_timeout(struct watchdog_device *wdd, ++ unsigned int timeout) ++{ ++ mpcore_wdt_stop(wdd); ++ wdt_timeout = timeout; ++ mpcore_wdt_start(wdd); ++ ++ return 0; ++} ++ ++static const struct watchdog_info mpcore_wdt_info = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++ .identity = "MPcore Watchdog", ++}; ++ ++static const struct watchdog_ops mpcore_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = mpcore_wdt_start, ++ .stop = mpcore_wdt_stop, ++ .ping = mpcore_wdt_keepalive, ++ .set_timeout = mpcore_wdt_set_timeout, ++}; ++ ++static struct watchdog_device mpcore_wdt = { ++ .info = &mpcore_wdt_info, ++ .ops = &mpcore_wdt_ops, ++ .min_timeout = 1, ++ .max_timeout = 65535, ++}; ++ ++static int mpcore_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ unsigned long rate = twd_timer_get_rate(); ++ ++ pr_info("MPCore WD init. clockrate: %u prescaler: %u countrate: %u timeout: %us\n", rate, 256, rate / 256, wdt_timeout); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -ENODEV; ++ ++ wdt_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(wdt_base)) ++ return PTR_ERR(wdt_base); ++ ++ watchdog_register_device(&mpcore_wdt); ++ return 0; ++} ++ ++static int mpcore_wdt_remove(struct platform_device *dev) ++{ ++ watchdog_unregister_device(&mpcore_wdt); ++ return 0; ++} ++ ++static struct platform_driver mpcore_wdt_driver = { ++ .probe = mpcore_wdt_probe, ++ .remove = mpcore_wdt_remove, ++ .driver = { ++ .name = "mpcore_wdt", ++ }, ++}; ++ ++module_platform_driver(mpcore_wdt_driver); ++MODULE_AUTHOR("Felix Fietkau <nbd@nbd.name>"); ++MODULE_LICENSE("GPL"); +--- a/arch/arm/include/asm/smp_twd.h ++++ b/arch/arm/include/asm/smp_twd.h +@@ -33,5 +33,6 @@ struct twd_local_timer name __initdata = + }; + + int twd_local_timer_register(struct twd_local_timer *); ++unsigned long twd_timer_get_rate(void); + + #endif +--- a/arch/arm/kernel/smp_twd.c ++++ b/arch/arm/kernel/smp_twd.c +@@ -15,6 +15,7 @@ + #include <linux/delay.h> + #include <linux/device.h> + #include <linux/err.h> ++#include <linux/export.h> + #include <linux/smp.h> + #include <linux/jiffies.h> + #include <linux/clockchips.h> +@@ -380,6 +381,14 @@ int __init twd_local_timer_register(stru + return twd_local_timer_common_register(NULL); + } + ++/* Needed by mpcore_wdt */ ++unsigned long twd_timer_get_rate(void) ++{ ++ return twd_timer_rate; ++} ++EXPORT_SYMBOL_GPL(twd_timer_get_rate); ++ ++ + #ifdef CONFIG_OF + static int __init twd_local_timer_of_register(struct device_node *np) + { |