Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 18491
b: refs/heads/master
c: eed6565
h: refs/heads/master
i:
  18489: 66a2e71
  18487: 860f583
v: v3
  • Loading branch information
Calin A. Culianu authored and Linus Torvalds committed Jan 15, 2006
1 parent eaaa01a commit cf0248e
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ee7be5de357b8ff69afc8c39648b336cd917218a
refs/heads/master: eed6565f70ce3fc958e5a3483c48fc4a8e111bdc
22 changes: 22 additions & 0 deletions trunk/drivers/char/watchdog/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,28 @@ config MACHZ_WDT
To compile this driver as a module, choose M here: the
module will be called machzwd.

config SBC_EPX_C3_WATCHDOG
tristate "Winsystems SBC EPX-C3 watchdog"
depends on WATCHDOG && X86
---help---
This is the driver for the built-in watchdog timer on the EPX-C3
Single-board computer made by Winsystems, Inc.

*Note*: This hardware watchdog is not probeable and thus there
is no way to know if writing to its IO address will corrupt
your system or have any real effect. The only way to be sure
that this driver does what you want is to make sure you
are runnning it on an EPX-C3 from Winsystems with the watchdog
timer at IO address 0x1ee and 0x1ef. It will write to both those
IO ports. Basically, the assumption is made that if you compile
this driver into your kernel and/or load it as a module, that you
know what you are doing and that you are in fact running on an
EPX-C3 board!

To compile this driver as a module, choose M here: the
module will be called sbc_epx_c3.


# PowerPC Architecture

config 8xx_WDT
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/char/watchdog/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o

# PowerPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
Expand Down
216 changes: 216 additions & 0 deletions trunk/drivers/char/watchdog/sbc_epx_c3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/*
* SBC EPX C3 0.1 A Hardware Watchdog Device for the Winsystems EPX-C3
* single board computer
*
* (c) Copyright 2006 Calin A. Culianu <calin@ajvar.org>, All Rights
* Reserved.
*
* 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.
*
* based on softdog.c by Alan Cox <alan@redhat.com>
*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define PFX "epx_c3: "
static int epx_c3_alive;

#define WATCHDOG_TIMEOUT 1 /* 1 sec default timeout */

static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");

#define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
#define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */

static void epx_c3_start(void)
{
outb(1, EPXC3_WATCHDOG_CTL_REG);
}

static void epx_c3_stop(void)
{

outb(0, EPXC3_WATCHDOG_CTL_REG);

printk(KERN_INFO PFX "Stopped watchdog timer.\n");
}

static void epx_c3_pet(void)
{
outb(1, EPXC3_WATCHDOG_PET_REG);
}

/*
* Allow only one person to hold it open
*/
static int epx_c3_open(struct inode *inode, struct file *file)
{
if (epx_c3_alive)
return -EBUSY;

if (nowayout)
__module_get(THIS_MODULE);

/* Activate timer */
epx_c3_start();
epx_c3_pet();

epx_c3_alive = 1;
printk(KERN_INFO "Started watchdog timer.\n");

return nonseekable_open(inode, file);
}

static int epx_c3_release(struct inode *inode, struct file *file)
{
/* Shut off the timer.
* Lock it in if it's a module and we defined ...NOWAYOUT */
if (!nowayout)
epx_c3_stop(); /* Turn the WDT off */

epx_c3_alive = 0;

return 0;
}

static ssize_t epx_c3_write(struct file *file, const char *data,
size_t len, loff_t *ppos)
{
/* Refresh the timer. */
if (len)
epx_c3_pet();
return len;
}

static int epx_c3_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int options, retval = -EINVAL;
static struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
.firmware_version = 0,
.identity = "Winsystems EPX-C3 H/W Watchdog",
};

switch (cmd) {
case WDIOC_GETSUPPORT:
if (copy_to_user((struct watchdog_info *)arg,
&ident, sizeof(ident)))
return -EFAULT;
return 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
return put_user(0,(int *)arg);
case WDIOC_KEEPALIVE:
epx_c3_pet();
return 0;
case WDIOC_GETTIMEOUT:
return put_user(WATCHDOG_TIMEOUT,(int *)arg);
case WDIOC_SETOPTIONS: {
if (get_user(options, (int *)arg))
return -EFAULT;

if (options & WDIOS_DISABLECARD) {
epx_c3_stop();
retval = 0;
}

if (options & WDIOS_ENABLECARD) {
epx_c3_start();
retval = 0;
}

return retval;
}
default:
return -ENOIOCTLCMD;
}
}

static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code,
void *unused)
{
if (code == SYS_DOWN || code == SYS_HALT)
epx_c3_stop(); /* Turn the WDT off */

return NOTIFY_DONE;
}

static struct file_operations epx_c3_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = epx_c3_write,
.ioctl = epx_c3_ioctl,
.open = epx_c3_open,
.release = epx_c3_release,
};

static struct miscdevice epx_c3_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &epx_c3_fops,
};

static struct notifier_block epx_c3_notifier = {
.notifier_call = epx_c3_notify_sys,
};

static const char banner[] __initdata =
KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";

static int __init watchdog_init(void)
{
int ret;

ret = register_reboot_notifier(&epx_c3_notifier);
if (ret) {
printk(KERN_ERR PFX "cannot register reboot notifier "
"(err=%d)\n", ret);
return ret;
}

ret = misc_register(&epx_c3_miscdev);
if (ret) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
"(err=%d)\n", WATCHDOG_MINOR, ret);
unregister_reboot_notifier(&epx_c3_notifier);
return ret;
}

printk(banner);

return 0;
}

static void __exit watchdog_exit(void)
{
misc_deregister(&epx_c3_miscdev);
unregister_reboot_notifier(&epx_c3_notifier);
}

module_init(watchdog_init);
module_exit(watchdog_exit);

MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

0 comments on commit cf0248e

Please sign in to comment.