[patch 1/1] watchdog driver for Digital-Logic MSM-P5XEN PC104 unit

From: ggaleotti
Date: Tue Oct 17 2006 - 08:35:04 EST




A simple watchdog driver for Digital-Logic's MSM-P5XEN PC104 unit.
The watchdog is a LTC1232 controlled by a single I/O port @ 0x1037.
The watchdog must be refreshed (writing a single byte) to the device
at least every 600 msecs (which is a little of overhead, but PC104
industrial applications requires a high degree of safety/reliability.)

Signed-off by: Gabriele Galeotti <ggaleotti@xxxxxxxxxxxx>
---

--- linux-2.6.18.1/MAINTAINERS.orig 2006-10-17 14:45:27.000000000 +0200
+++ linux-2.6.18.1/MAINTAINERS 2006-10-17 14:43:02.000000000 +0200
@@ -3355,6 +3355,12 @@ M: fuganti@xxxxxxxxxxxxxx
W: http://cvs.conectiva.com.br/drivers/ZFL-watchdog/
S: Maintained

+DIGITAL-LOGIC PC104 MSM-P5XEN WATCHDOG DRIVER
+P: Gabriele Galeotti
+M: ggaleotti@xxxxxxxxxxxx
+W: http://ggaleotti.interfree.it
+S: Maintained
+
ZR36067 VIDEO FOR LINUX DRIVER
P: Ronald Bultje
M: rbultje@xxxxxxxxxxxxxxxxxxx
--- linux-2.6.18.1/drivers/char/watchdog/Kconfig.orig 2006-10-17 14:44:45.000000000 +0200
+++ linux-2.6.18.1/drivers/char/watchdog/Kconfig 2006-10-17 14:46:59.000000000 +0200
@@ -433,6 +433,20 @@ config SBC_EPX_C3_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called sbc_epx_c3.

+config DLPC104_WATCHDOG
+ tristate "Digital-Logic MSM-P5XEN PC104 unit Watchdog"
+ depends on WATCHDOG && X86
+ ---help---
+ This is the driver for the built-in watchdog timer on the MSM-P5XEN
+ PC104 unit made by Digital-Logic. If you fail to refresh the watchdog
+ at least every 600 msecs (writing a byte to the device), it will
+ reboot your machine. The watchdog chip is a LTC1232 controlled by a
+ single I/O port @ 0x1037.
+
+ *Note*: This hardware watchdog is not probeable nor configurable.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dlpc104.

# PowerPC Architecture

--- linux-2.6.18.1/drivers/char/watchdog/Makefile.orig 2006-10-17 14:44:26.000000000 +0200
+++ linux-2.6.18.1/drivers/char/watchdog/Makefile 2006-10-17 14:47:35.000000000 +0200
@@ -55,6 +55,7 @@ obj-$(CONFIG_W83877F_WDT) += w83877f_wdt
obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
+obj-$(CONFIG_DLPC104_WATCHDOG) += dlpc104.o

# PowerPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
--- linux-2.6.18.1/drivers/char/watchdog/dlpc104.c.orig 2006-10-17 14:48:39.000000000 +0200
+++ linux-2.6.18.1/drivers/char/watchdog/dlpc104.c 2006-10-17 14:48:27.000000000 +0200
@@ -0,0 +1,228 @@
+
+/*
+ * dlpc104: watchdog driver for Digital-Logic MSM-P5XEN PC104 unit
+ *
+ * Copyright (c) 2006 Gabriele Galeotti <ggaleotti@xxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Version 0.1 (06/10/2006):
+ * - first version
+ *
+ * Please see ggaleotti.interfree.it for latest version.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <linux/atmdev.h>
+#include <linux/miscdevice.h>
+
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+
+#define WDT_IOBASE 0x1000
+#define WDT_OFFSET 0x37
+
+static int io_base = WDT_IOBASE;
+module_param(io_base, int, 0);
+MODULE_PARM_DESC(io_base, "I/O base address (default=0x1000)");
+
+static struct timer_list wdt_timer;
+
+static void
+wdt_enable(unsigned long data)
+{
+ (void)data;
+
+ outb(inb(io_base + WDT_OFFSET) & 0xf7, io_base + WDT_OFFSET);
+}
+
+static void
+wdt_disable(void)
+{
+ outb(inb(io_base + WDT_OFFSET) | 0x08, io_base + WDT_OFFSET);
+}
+
+static void
+wdt_ping(void)
+{
+ /*
+ * Clear-pulse trailing edge scheduling.
+ *
+ * We use mod_timer() rather than add_timer() because a timer could
+ * be already activated.
+ * kernel/timer.c:
+ * "... since add_timer() cannot modify an already running timer."
+ */
+ mod_timer(&wdt_timer, jiffies + (HZ / 10));
+
+ wdt_disable();
+}
+
+static int
+dl_wdt_open(struct inode *inode, struct file *file)
+{
+ wdt_enable(0);
+
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t
+dl_wdt_write(struct file *file, const char *data, size_t length, loff_t *ppos)
+{
+ (void)file;
+ (void)data;
+ (void)ppos;
+
+ if (length != 0)
+ {
+ wdt_ping();
+ }
+
+ return length;
+}
+
+static int
+dl_wdt_close(struct inode *inode, struct file *file)
+{
+ del_timer(&wdt_timer);
+
+ wdt_disable();
+
+ return 0;
+}
+
+static struct watchdog_info identity = {
+ .options = 0,
+ .identity = "DLPC104 Watchdog",
+ };
+
+static int
+dl_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int return_status;
+
+ switch (cmd)
+ {
+ case WDIOC_GETSUPPORT:
+ return_status = copy_to_user((struct watchdog_info *)arg, &identity, sizeof(identity)) ? -EFAULT : 0;
+ break;
+ default:
+ return_status = -ENOIOCTLCMD;
+ break;
+ }
+
+ return return_status;
+}
+
+static int
+wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ {
+ del_timer(&wdt_timer);
+ wdt_disable();
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct file_operations dlmodule_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = dl_wdt_write,
+ .ioctl = dl_wdt_ioctl,
+ .open = dl_wdt_open,
+ .release = dl_wdt_close
+ };
+
+static struct miscdevice dlmodule_miscdevice = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &dlmodule_fops,
+ };
+
+/*
+ * The WDT needs to learn about soft shutdowns in order to turn the timebomb
+ * registers off.
+ */
+static struct notifier_block wdt_notifier = {
+ .notifier_call = wdt_notify_sys,
+ };
+
+static int __init
+dlmodule_init(void)
+{
+ int result;
+
+ if (!request_region(io_base + WDT_OFFSET, 1, "DLPC104 Watchdog"))
+ {
+ printk(KERN_ERR "DLPC104 Watchdog: I/O region busy.\n");
+ result = -EBUSY;
+ goto exit_0;
+ }
+
+ result = register_reboot_notifier(&wdt_notifier);
+ if (result != 0)
+ {
+ printk (KERN_ERR "DLPC104 Watchdog: cannot register reboot notifier.\n");
+ goto exit_1;
+ }
+
+ result = misc_register(&dlmodule_miscdevice);
+ if (result != 0)
+ {
+ printk(KERN_ERR "DLPC104 Watchdog: cannot register.\n");
+ goto exit_2;
+ }
+
+ init_timer(&wdt_timer);
+ wdt_timer.function = wdt_enable;
+ wdt_timer.data = 0;
+
+ printk("Digital-Logic MSM-P5XEN PC104 Watchdog driver loaded.\n");
+
+ return 0;
+
+exit_2: unregister_reboot_notifier(&wdt_notifier);
+exit_1: release_region(io_base + WDT_OFFSET, 1);
+exit_0: return result;
+}
+
+static void __exit
+dlmodule_exit(void)
+{
+ del_timer(&wdt_timer);
+ wdt_disable();
+
+ release_region(io_base + WDT_OFFSET, 1);
+
+ unregister_reboot_notifier(&wdt_notifier);
+
+ misc_deregister(&dlmodule_miscdevice);
+}
+
+/*
+ * Module parameters & definitions.
+ */
+
+MODULE_AUTHOR("Gabriele Galeotti <ggaleotti@xxxxxxxxxxxx>");
+MODULE_DESCRIPTION("Digital-Logic PC104 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+module_init(dlmodule_init);
+module_exit(dlmodule_exit);
+


------------------------------------------------------------
Sei stanco di girare a vuoto?
Con il nuovo motore di ricerca Interfree trovi di tutto.
Vieni a trovarci: http://search.interfree.it/

Lo Staff di Interfree
------------------------------------------------------------

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/