diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 4 | ||||
-rw-r--r-- | drivers/watchdog/at91rm9200_wdt.c | 61 | ||||
-rw-r--r-- | drivers/watchdog/bcm_kona_wdt.c | 27 | ||||
-rw-r--r-- | drivers/watchdog/diag288_wdt.c | 20 | ||||
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 51 | ||||
-rw-r--r-- | drivers/watchdog/octeon-wdt-main.c | 201 | ||||
-rw-r--r-- | drivers/watchdog/pnx4008_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/qcom-wdt.c | 21 | ||||
-rw-r--r-- | drivers/watchdog/stmp3xxx_rtc_wdt.c | 4 |
9 files changed, 194 insertions, 197 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 16f202350997..e5e7c5505de7 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -154,7 +154,7 @@ config ARM_SP805_WATCHDOG config AT91RM9200_WATCHDOG tristate "AT91RM9200 watchdog" - depends on SOC_AT91RM9200 + depends on SOC_AT91RM9200 && MFD_SYSCON help Watchdog timer embedded into AT91RM9200 chips. This will reboot your system when the timeout is reached. @@ -169,7 +169,6 @@ config AT91SAM9X_WATCHDOG config CADENCE_WATCHDOG tristate "Cadence Watchdog Timer" - depends on ARM select WATCHDOG_CORE help Say Y here if you want to include support for the watchdog @@ -1190,6 +1189,7 @@ config OCTEON_WDT tristate "Cavium OCTEON SOC family Watchdog Timer" depends on CAVIUM_OCTEON_SOC default y + select WATCHDOG_CORE select EXPORT_UASM if OCTEON_WDT = m help Hardware driver for OCTEON's on chip watchdog timer. diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index d244112d5b6f..41cecb55766c 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c @@ -12,27 +12,32 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/bitops.h> +#include <linux/delay.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/atmel-st.h> #include <linux/miscdevice.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/platform_device.h> +#include <linux/reboot.h> +#include <linux/regmap.h> #include <linux/types.h> #include <linux/watchdog.h> #include <linux/uaccess.h> #include <linux/of.h> #include <linux/of_device.h> -#include <mach/at91_st.h> #define WDT_DEFAULT_TIME 5 /* seconds */ #define WDT_MAX_TIME 256 /* seconds */ static int wdt_time = WDT_DEFAULT_TIME; static bool nowayout = WATCHDOG_NOWAYOUT; +static struct regmap *regmap_st; module_param(wdt_time, int, 0); MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default=" @@ -50,12 +55,33 @@ static unsigned long at91wdt_busy; /* ......................................................................... */ +static int at91rm9200_restart(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + /* + * Perform a hardware reset with the use of the Watchdog timer. + */ + regmap_write(regmap_st, AT91_ST_WDMR, + AT91_ST_RSTEN | AT91_ST_EXTEN | 1); + regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST); + + mdelay(2000); + + pr_emerg("Unable to restart system\n"); + return NOTIFY_DONE; +} + +static struct notifier_block at91rm9200_restart_nb = { + .notifier_call = at91rm9200_restart, + .priority = 192, +}; + /* * Disable the watchdog. */ static inline void at91_wdt_stop(void) { - at91_st_write(AT91_ST_WDMR, AT91_ST_EXTEN); + regmap_write(regmap_st, AT91_ST_WDMR, AT91_ST_EXTEN); } /* @@ -63,9 +89,9 @@ static inline void at91_wdt_stop(void) */ static inline void at91_wdt_start(void) { - at91_st_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | + regmap_write(regmap_st, AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); - at91_st_write(AT91_ST_CR, AT91_ST_WDRST); + regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST); } /* @@ -73,7 +99,7 @@ static inline void at91_wdt_start(void) */ static inline void at91_wdt_reload(void) { - at91_st_write(AT91_ST_CR, AT91_ST_WDRST); + regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST); } /* ......................................................................... */ @@ -203,16 +229,32 @@ static struct miscdevice at91wdt_miscdev = { static int at91wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct device *parent; int res; if (at91wdt_miscdev.parent) return -EBUSY; at91wdt_miscdev.parent = &pdev->dev; + parent = dev->parent; + if (!parent) { + dev_err(dev, "no parent\n"); + return -ENODEV; + } + + regmap_st = syscon_node_to_regmap(parent->of_node); + if (!regmap_st) + return -ENODEV; + res = misc_register(&at91wdt_miscdev); if (res) return res; + res = register_restart_handler(&at91rm9200_restart_nb); + if (res) + dev_warn(dev, "failed to register restart handler\n"); + pr_info("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); return 0; @@ -220,8 +262,13 @@ static int at91wdt_probe(struct platform_device *pdev) static int at91wdt_remove(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int res; + res = unregister_restart_handler(&at91rm9200_restart_nb); + if (res) + dev_warn(dev, "failed to unregister restart handler\n"); + res = misc_deregister(&at91wdt_miscdev); if (!res) at91wdt_miscdev.parent = NULL; @@ -267,7 +314,7 @@ static struct platform_driver at91wdt_driver = { .suspend = at91wdt_suspend, .resume = at91wdt_resume, .driver = { - .name = "at91_wdt", + .name = "atmel_st_watchdog", .of_match_table = at91_wdt_dt_ids, }, }; @@ -296,4 +343,4 @@ module_exit(at91_wdt_exit); MODULE_AUTHOR("Andrew Victor"); MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:at91_wdt"); +MODULE_ALIAS("platform:atmel_st_watchdog"); diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c index 4e37db3539a4..22d8ae65772a 100644 --- a/drivers/watchdog/bcm_kona_wdt.c +++ b/drivers/watchdog/bcm_kona_wdt.c @@ -99,12 +99,14 @@ static int secure_register_read(struct bcm_kona_wdt *wdt, uint32_t offset) static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data) { - int ctl_val, cur_val, ret; + int ctl_val, cur_val; unsigned long flags; struct bcm_kona_wdt *wdt = s->private; - if (!wdt) - return seq_puts(s, "No device pointer\n"); + if (!wdt) { + seq_puts(s, "No device pointer\n"); + return 0; + } spin_lock_irqsave(&wdt->lock, flags); ctl_val = secure_register_read(wdt, SECWDOG_CTRL_REG); @@ -112,7 +114,7 @@ static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data) spin_unlock_irqrestore(&wdt->lock, flags); if (ctl_val < 0 || cur_val < 0) { - ret = seq_puts(s, "Error accessing hardware\n"); + seq_puts(s, "Error accessing hardware\n"); } else { int ctl, cur, ctl_sec, cur_sec, res; @@ -121,15 +123,18 @@ static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data) cur = cur_val & SECWDOG_COUNT_MASK; ctl_sec = TICKS_TO_SECS(ctl, wdt); cur_sec = TICKS_TO_SECS(cur, wdt); - ret = seq_printf(s, "Resolution: %d / %d\n" - "Control: %d s / %d (%#x) ticks\n" - "Current: %d s / %d (%#x) ticks\n" - "Busy count: %lu\n", res, - wdt->resolution, ctl_sec, ctl, ctl, cur_sec, - cur, cur, wdt->busy_count); + seq_printf(s, + "Resolution: %d / %d\n" + "Control: %d s / %d (%#x) ticks\n" + "Current: %d s / %d (%#x) ticks\n" + "Busy count: %lu\n", + res, wdt->resolution, + ctl_sec, ctl, ctl, + cur_sec, cur, cur, + wdt->busy_count); } - return ret; + return 0; } static int bcm_kona_dbg_open(struct inode *inode, struct file *file) diff --git a/drivers/watchdog/diag288_wdt.c b/drivers/watchdog/diag288_wdt.c index 429494b6c822..a9a5210143ae 100644 --- a/drivers/watchdog/diag288_wdt.c +++ b/drivers/watchdog/diag288_wdt.c @@ -125,9 +125,7 @@ static int wdt_start(struct watchdog_device *dev) ret = __diag288_vm(func, dev->timeout, ebc_cmd, len); WARN_ON(ret != 0); kfree(ebc_cmd); - } - - if (MACHINE_IS_LPAR) { + } else { ret = __diag288_lpar(WDT_FUNC_INIT, dev->timeout, LPARWDT_RESTART); } @@ -136,7 +134,6 @@ static int wdt_start(struct watchdog_device *dev) pr_err("The watchdog cannot be activated\n"); return ret; } - pr_info("The watchdog was activated\n"); return 0; } @@ -145,7 +142,6 @@ static int wdt_stop(struct watchdog_device *dev) int ret; ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0); - pr_info("The watchdog was deactivated\n"); return ret; } @@ -177,10 +173,9 @@ static int wdt_ping(struct watchdog_device *dev) ret = __diag288_vm(func, dev->timeout, ebc_cmd, len); WARN_ON(ret != 0); kfree(ebc_cmd); - } - - if (MACHINE_IS_LPAR) + } else { ret = __diag288_lpar(WDT_FUNC_CHANGE, dev->timeout, 0); + } if (ret) pr_err("The watchdog timer cannot be started or reset\n"); @@ -202,7 +197,7 @@ static struct watchdog_ops wdt_ops = { }; static struct watchdog_info wdt_info = { - .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 0, .identity = "z Watchdog", }; @@ -273,21 +268,16 @@ static int __init diag288_init(void) watchdog_set_nowayout(&wdt_dev, nowayout_info); if (MACHINE_IS_VM) { - pr_info("The watchdog device driver detected a z/VM environment\n"); if (__diag288_vm(WDT_FUNC_INIT, 15, ebc_begin, sizeof(ebc_begin)) != 0) { pr_err("The watchdog cannot be initialized\n"); return -EINVAL; } - } else if (MACHINE_IS_LPAR) { - pr_info("The watchdog device driver detected an LPAR environment\n"); + } else { if (__diag288_lpar(WDT_FUNC_INIT, 30, LPARWDT_RESTART)) { pr_err("The watchdog cannot be initialized\n"); return -EINVAL; } - } else { - pr_err("Linux runs in an environment that does not support the diag288 watchdog\n"); - return -ENODEV; } if (__diag288_lpar(WDT_FUNC_CANCEL, 0, 0)) { diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 05ee0bf88ce9..3c3fd417ddeb 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -51,6 +51,7 @@ #define DRV_VERSION "1.11" /* Includes */ +#include <linux/acpi.h> /* For ACPI support */ #include <linux/module.h> /* For module specific items */ #include <linux/moduleparam.h> /* For new moduleparam's */ #include <linux/types.h> /* For standard types (like size_t) */ @@ -103,6 +104,8 @@ static struct { /* this is private data for the iTCO_wdt device */ struct platform_device *dev; /* the PCI-device */ struct pci_dev *pdev; + /* whether or not the watchdog has been suspended */ + bool suspended; } iTCO_wdt_private; /* module parameters */ @@ -571,12 +574,60 @@ static void iTCO_wdt_shutdown(struct platform_device *dev) iTCO_wdt_stop(NULL); } +#ifdef CONFIG_PM_SLEEP +/* + * Suspend-to-idle requires this, because it stops the ticks and timekeeping, so + * the watchdog cannot be pinged while in that state. In ACPI sleep states the + * watchdog is stopped by the platform firmware. + */ + +#ifdef CONFIG_ACPI +static inline bool need_suspend(void) +{ + return acpi_target_system_state() == ACPI_STATE_S0; +} +#else +static inline bool need_suspend(void) { return true; } +#endif + +static int iTCO_wdt_suspend_noirq(struct device *dev) +{ + int ret = 0; + + iTCO_wdt_private.suspended = false; + if (watchdog_active(&iTCO_wdt_watchdog_dev) && need_suspend()) { + ret = iTCO_wdt_stop(&iTCO_wdt_watchdog_dev); + if (!ret) + iTCO_wdt_private.suspended = true; + } + return ret; +} + +static int iTCO_wdt_resume_noirq(struct device *dev) +{ + if (iTCO_wdt_private.suspended) + iTCO_wdt_start(&iTCO_wdt_watchdog_dev); + + return 0; +} + +static struct dev_pm_ops iTCO_wdt_pm = { + .suspend_noirq = iTCO_wdt_suspend_noirq, + .resume_noirq = iTCO_wdt_resume_noirq, +}; + +#define ITCO_WDT_PM_OPS (&iTCO_wdt_pm) +#else +#define ITCO_WDT_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static struct platform_driver iTCO_wdt_driver = { .probe = iTCO_wdt_probe, .remove = iTCO_wdt_remove, .shutdown = iTCO_wdt_shutdown, .driver = { .name = DRV_NAME, + .pm = ITCO_WDT_PM_OPS, }, }; diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 8453531545df..14521c8b3d5a 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c @@ -3,6 +3,8 @@ * * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks * + * Converted to use WATCHDOG_CORE by Aaro Koskinen <aaro.koskinen@iki.fi>. + * * Some parts derived from wdt.c * * (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>, @@ -103,13 +105,10 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -static unsigned long octeon_wdt_is_open; -static char expect_close; - -static u32 __initdata nmi_stage1_insns[64]; +static u32 nmi_stage1_insns[64] __initdata; /* We need one branch and therefore one relocation per target label. */ -static struct uasm_label __initdata labels[5]; -static struct uasm_reloc __initdata relocs[5]; +static struct uasm_label labels[5] __initdata; +static struct uasm_reloc relocs[5] __initdata; enum lable_id { label_enter_bootloader = 1 @@ -218,7 +217,8 @@ static void __init octeon_wdt_build_stage1(void) pr_debug("\t.set pop\n"); if (len > 32) - panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", len); + panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", + len); } static int cpu2core(int cpu) @@ -294,6 +294,7 @@ static void octeon_wdt_write_hex(u64 value, int digits) { int d; int v; + for (d = 0; d < digits; d++) { v = (value >> ((digits - d - 1) * 4)) & 0xf; if (v >= 10) @@ -303,7 +304,7 @@ static void octeon_wdt_write_hex(u64 value, int digits) } } -const char *reg_name[] = { +static const char reg_name[][3] = { "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", @@ -444,7 +445,7 @@ static int octeon_wdt_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static void octeon_wdt_ping(void) +static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog) { int cpu; int coreid; @@ -457,10 +458,12 @@ static void octeon_wdt_ping(void) !cpumask_test_cpu(cpu, &irq_enabled_cpus)) { /* We have to enable the irq */ int irq = OCTEON_IRQ_WDOG0 + coreid; + enable_irq(irq); cpumask_set_cpu(cpu, &irq_enabled_cpus); } } + return 0; } static void octeon_wdt_calc_parameters(int t) @@ -489,7 +492,8 @@ static void octeon_wdt_calc_parameters(int t) timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8; } -static int octeon_wdt_set_heartbeat(int t) +static int octeon_wdt_set_timeout(struct watchdog_device *wdog, + unsigned int t) { int cpu; int coreid; @@ -509,158 +513,45 @@ static int octeon_wdt_set_heartbeat(int t) cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64); cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); } - octeon_wdt_ping(); /* Get the irqs back on. */ + octeon_wdt_ping(wdog); /* Get the irqs back on. */ return 0; } -/** - * octeon_wdt_write: - * @file: file handle to the watchdog - * @buf: buffer to write (unused as data does not matter here - * @count: count of bytes - * @ppos: pointer to the position to write. No seeks allowed - * - * A write to a watchdog device is defined as a keepalive signal. Any - * write of data will do, as we we don't define content meaning. - */ - -static ssize_t octeon_wdt_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - if (count) { - if (!nowayout) { - size_t i; - - /* In case it was set long ago */ - expect_close = 0; - - for (i = 0; i != count; i++) { - char c; - if (get_user(c, buf + i)) - return -EFAULT; - if (c == 'V') - expect_close = 1; - } - } - octeon_wdt_ping(); - } - return count; -} - -/** - * octeon_wdt_ioctl: - * @file: file handle to the device - * @cmd: watchdog command - * @arg: argument pointer - * - * The watchdog API defines a common set of functions for all - * watchdogs according to their available features. We only - * actually usefully support querying capabilities and setting - * the timeout. - */ - -static long octeon_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - int new_heartbeat; - - static struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT| - WDIOF_MAGICCLOSE| - WDIOF_KEEPALIVEPING, - .firmware_version = 1, - .identity = "OCTEON", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, p); - case WDIOC_KEEPALIVE: - octeon_wdt_ping(); - return 0; - case WDIOC_SETTIMEOUT: - if (get_user(new_heartbeat, p)) - return -EFAULT; - if (octeon_wdt_set_heartbeat(new_heartbeat)) - return -EINVAL; - /* Fall through. */ - case WDIOC_GETTIMEOUT: - return put_user(heartbeat, p); - default: - return -ENOTTY; - } -} - -/** - * octeon_wdt_open: - * @inode: inode of device - * @file: file handle to device - * - * The watchdog device has been opened. The watchdog device is single - * open and on opening we do a ping to reset the counters. - */ - -static int octeon_wdt_open(struct inode *inode, struct file *file) +static int octeon_wdt_start(struct watchdog_device *wdog) { - if (test_and_set_bit(0, &octeon_wdt_is_open)) - return -EBUSY; - /* - * Activate - */ - octeon_wdt_ping(); + octeon_wdt_ping(wdog); do_coundown = 1; - return nonseekable_open(inode, file); + return 0; } -/** - * octeon_wdt_release: - * @inode: inode to board - * @file: file handle to board - * - * The watchdog has a configurable API. There is a religious dispute - * between people who want their watchdog to be able to shut down and - * those who want to be sure if the watchdog manager dies the machine - * reboots. In the former case we disable the counters, in the latter - * case you have to open it again very soon. - */ - -static int octeon_wdt_release(struct inode *inode, struct file *file) +static int octeon_wdt_stop(struct watchdog_device *wdog) { - if (expect_close) { - do_coundown = 0; - octeon_wdt_ping(); - } else { - pr_crit("WDT device closed unexpectedly. WDT will not stop!\n"); - } - clear_bit(0, &octeon_wdt_is_open); - expect_close = 0; + do_coundown = 0; + octeon_wdt_ping(wdog); return 0; } -static const struct file_operations octeon_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = octeon_wdt_write, - .unlocked_ioctl = octeon_wdt_ioctl, - .open = octeon_wdt_open, - .release = octeon_wdt_release, +static struct notifier_block octeon_wdt_cpu_notifier = { + .notifier_call = octeon_wdt_cpu_callback, }; -static struct miscdevice octeon_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &octeon_wdt_fops, +static const struct watchdog_info octeon_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, + .identity = "OCTEON", }; -static struct notifier_block octeon_wdt_cpu_notifier = { - .notifier_call = octeon_wdt_cpu_callback, +static const struct watchdog_ops octeon_wdt_ops = { + .owner = THIS_MODULE, + .start = octeon_wdt_start, + .stop = octeon_wdt_stop, + .ping = octeon_wdt_ping, + .set_timeout = octeon_wdt_set_timeout, }; +static struct watchdog_device octeon_wdt = { + .info = &octeon_wdt_info, + .ops = &octeon_wdt_ops, +}; /** * Module/ driver initialization. @@ -685,7 +576,8 @@ static int __init octeon_wdt_init(void) max_timeout_sec = 6; do { max_timeout_sec--; - timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * max_timeout_sec) >> 8; + timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * + max_timeout_sec) >> 8; } while (timeout_cnt > 65535); BUG_ON(timeout_cnt == 0); @@ -694,11 +586,15 @@ static int __init octeon_wdt_init(void) pr_info("Initial granularity %d Sec\n", timeout_sec); - ret = misc_register(&octeon_wdt_miscdev); + octeon_wdt.timeout = timeout_sec; + octeon_wdt.max_timeout = UINT_MAX; + + watchdog_set_nowayout(&octeon_wdt, nowayout); + + ret = watchdog_register_device(&octeon_wdt); if (ret) { - pr_err("cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); - goto out; + pr_err("watchdog_register_device() failed: %d\n", ret); + return ret; } /* Build the NMI handler ... */ @@ -721,8 +617,7 @@ static int __init octeon_wdt_init(void) __register_hotcpu_notifier(&octeon_wdt_cpu_notifier); cpu_notifier_register_done(); -out: - return ret; + return 0; } /** @@ -732,7 +627,7 @@ static void __exit octeon_wdt_cleanup(void) { int cpu; - misc_deregister(&octeon_wdt_miscdev); + watchdog_unregister_device(&octeon_wdt); cpu_notifier_register_begin(); __unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier); diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 55e220150103..b9c6049c3e78 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -216,7 +216,7 @@ static struct platform_driver platform_wdt_driver = { module_platform_driver(platform_wdt_driver); MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); -MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); +MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>"); MODULE_DESCRIPTION("PNX4008 Watchdog Driver"); module_param(heartbeat, uint, 0); diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index aa85618c4d03..aa03ca8f2d9b 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -20,9 +20,9 @@ #include <linux/reboot.h> #include <linux/watchdog.h> -#define WDT_RST 0x0 -#define WDT_EN 0x8 -#define WDT_BITE_TIME 0x24 +#define WDT_RST 0x38 +#define WDT_EN 0x40 +#define WDT_BITE_TIME 0x5C struct qcom_wdt { struct watchdog_device wdd; @@ -117,6 +117,8 @@ static int qcom_wdt_probe(struct platform_device *pdev) { struct qcom_wdt *wdt; struct resource *res; + struct device_node *np = pdev->dev.of_node; + u32 percpu_offset; int ret; wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); @@ -124,6 +126,14 @@ static int qcom_wdt_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + /* We use CPU0's DGT for the watchdog */ + if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) + percpu_offset = 0; + + res->start += percpu_offset; + res->end += percpu_offset; + wdt->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); @@ -203,9 +213,8 @@ static int qcom_wdt_remove(struct platform_device *pdev) } static const struct of_device_id qcom_wdt_of_table[] = { - { .compatible = "qcom,kpss-wdt-msm8960", }, - { .compatible = "qcom,kpss-wdt-apq8064", }, - { .compatible = "qcom,kpss-wdt-ipq8064", }, + { .compatible = "qcom,kpss-timer" }, + { .compatible = "qcom,scss-timer" }, { }, }; MODULE_DEVICE_TABLE(of, qcom_wdt_of_table); diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c index a62b1b6decf4..e7f0d5b60d3d 100644 --- a/drivers/watchdog/stmp3xxx_rtc_wdt.c +++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c @@ -1,7 +1,7 @@ /* * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28 * - * Author: Wolfram Sang <w.sang@pengutronix.de> + * Author: Wolfram Sang <kernel@pengutronix.de> * * Copyright (C) 2011-12 Wolfram Sang, Pengutronix * @@ -129,4 +129,4 @@ module_platform_driver(stmp3xxx_wdt_driver); MODULE_DESCRIPTION("STMP3XXX RTC Watchdog Driver"); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); +MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>"); |