// SPDX-License-Identifier: GPL-2.0-or-later /* * IDT Interprise 79RC32434 watchdog driver * * Copyright (C) 2006, Ondrej Zajicek <santiago@crfreenet.org> * Copyright (C) 2008, Florian Fainelli <florian@openwrt.org> * * based on * SoftDog 0.05: A Software Watchdog Device * * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>, * All Rights Reserved.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#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) */ #include <linux/errno.h> /* For the -ENODEV/... values */ #include <linux/kernel.h> /* For printk/panic/... */ #include <linux/fs.h> /* For file operations */ #include <linux/miscdevice.h> /* For struct miscdevice */ #include <linux/watchdog.h> /* For the watchdog specific items */ #include <linux/init.h> /* For __init/__exit/... */ #include <linux/platform_device.h> /* For platform_driver framework */ #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ #include <linux/io.h> /* For devm_ioremap */
#include <asm/mach-rc32434/integ.h> /* For the Watchdog registers */
/* Board internal clock speed in Hz,
* the watchdog timer ticks at. */ externunsignedint idt_cpu_freq;
/* translate wtcompare value to seconds and vice versa */ #define WTCOMP2SEC(x) (x / idt_cpu_freq) #define SEC2WTCOMP(x) (x * idt_cpu_freq)
/* Use a default timeout of 20s. This should be * safe for CPU clock speeds up to 400MHz, as
* ((2 ^ 32) - 1) / (400MHz / 2) = 21s. */ #define WATCHDOG_TIMEOUT 20
staticbool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/* apply or and nand masks to data read from addr and write back */ #define SET_BITS(addr, or, nand) \
writel((readl(&addr) | or) & ~nand, &addr)
staticint rc32434_wdt_set(int new_timeout)
{ int max_to = WTCOMP2SEC((u32)-1);
if (new_timeout < 0 || new_timeout > max_to) {
pr_err("timeout value must be between 0 and %d\n", max_to); return -EINVAL;
}
timeout = new_timeout;
spin_lock(&rc32434_wdt_device.io_lock);
writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare);
spin_unlock(&rc32434_wdt_device.io_lock);
staticint rc32434_wdt_probe(struct platform_device *pdev)
{ int ret; struct resource *r;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res"); if (!r) {
pr_err("failed to retrieve resources\n"); return -ENODEV;
}
wdt_reg = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!wdt_reg) {
pr_err("failed to remap I/O resources\n"); return -ENXIO;
}
spin_lock_init(&rc32434_wdt_device.io_lock);
/* Make sure the watchdog is not running */
rc32434_wdt_stop();
/* Check that the heartbeat value is within it's range;
* if not reset to the default */ if (rc32434_wdt_set(timeout)) {
rc32434_wdt_set(WATCHDOG_TIMEOUT);
pr_info("timeout value must be between 0 and %d\n",
WTCOMP2SEC((u32)-1));
}
ret = misc_register(&rc32434_wdt_miscdev); if (ret < 0) {
pr_err("failed to register watchdog device\n"); return ret;
}
pr_info("Watchdog Timer version " VERSION ", timer margin: %d sec\n",
timeout);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.