Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
5cb1fc6d
Commit
5cb1fc6d
authored
Sep 01, 2003
by
Wim Van Sebroeck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[WATCHDOG] alim1535_wdt.c
Add "ALi M1535 PMU Watchdog Timer" driver
parent
742b6079
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
478 additions
and
0 deletions
+478
-0
drivers/char/watchdog/Kconfig
drivers/char/watchdog/Kconfig
+12
-0
drivers/char/watchdog/Makefile
drivers/char/watchdog/Makefile
+1
-0
drivers/char/watchdog/alim1535_wdt.c
drivers/char/watchdog/alim1535_wdt.c
+465
-0
No files found.
drivers/char/watchdog/Kconfig
View file @
5cb1fc6d
...
...
@@ -346,6 +346,18 @@ config ALIM7101_WDT
module, say M here and read <file:Documentation/modules.txt>. Most
people will say N.
config ALIM1535_WDT
tristate "ALi M1535 PMU Watchdog Timer"
depends on WATCHDOG
---help---
This is the driver for the hardware watchdog on the ALi M1535 PMU.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module is called alim1535_wdt. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. Most
people will say N.
config SC1200_WDT
tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
depends on WATCHDOG
...
...
drivers/char/watchdog/Makefile
View file @
5cb1fc6d
...
...
@@ -27,6 +27,7 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
obj-$(CONFIG_W83877F_WDT)
+=
w83877f_wdt.o
obj-$(CONFIG_SC520_WDT)
+=
sc520_wdt.o
obj-$(CONFIG_ALIM7101_WDT)
+=
alim7101_wdt.o
obj-$(CONFIG_ALIM1535_WDT)
+=
alim1535_wdt.o
obj-$(CONFIG_SC1200_WDT)
+=
sc1200wdt.o
obj-$(CONFIG_WAFER_WDT)
+=
wafer5823wdt.o
obj-$(CONFIG_CPU5_WDT)
+=
cpu5wdt.o
...
...
drivers/char/watchdog/alim1535_wdt.c
0 → 100644
View file @
5cb1fc6d
/*
* Watchdog for the 7101 PMU version found in the ALi M1535 chipsets
*
* 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.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/ioport.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define WATCHDOG_NAME "ALi_M1535"
#define PFX WATCHDOG_NAME ": "
#define WATCHDOG_TIMEOUT 60
/* 60 sec default timeout */
/* internal variables */
static
unsigned
long
ali_is_open
;
static
char
ali_expect_release
;
static
struct
pci_dev
*
ali_pci
;
static
u32
ali_timeout_bits
;
/* stores the computed timeout */
static
spinlock_t
ali_lock
;
/* Guards the hardware */
/* module parameters */
static
int
timeout
=
WATCHDOG_TIMEOUT
;
module_param
(
timeout
,
int
,
0
);
MODULE_PARM_DESC
(
timeout
,
"Watchdog timeout in seconds. (0<timeout<18000, default="
__MODULE_STRING
(
WATCHDOG_TIMEOUT
)
")"
);
#ifdef CONFIG_WATCHDOG_NOWAYOUT
static
int
nowayout
=
1
;
#else
static
int
nowayout
=
0
;
#endif
module_param
(
nowayout
,
int
,
0
);
MODULE_PARM_DESC
(
nowayout
,
"Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"
);
/*
* ali_start - start watchdog countdown
*
* Starts the timer running providing the timer has a counter
* configuration set.
*/
static
void
ali_start
(
void
)
{
u32
val
;
spin_lock
(
&
ali_lock
);
pci_read_config_dword
(
ali_pci
,
0xCC
,
&
val
);
val
&=
~
0x3F
;
/* Mask count */
val
|=
(
1
<<
25
)
|
ali_timeout_bits
;
pci_write_config_dword
(
ali_pci
,
0xCC
,
val
);
spin_unlock
(
&
ali_lock
);
}
/*
* ali_stop - stop the timer countdown
*
* Stop the ALi watchdog countdown
*/
static
void
ali_stop
(
void
)
{
u32
val
;
spin_lock
(
&
ali_lock
);
pci_read_config_dword
(
ali_pci
,
0xCC
,
&
val
);
val
&=
~
0x3F
;
/* Mask count to zero (disabled) */
val
&=
~
(
1
<<
25
);
/* and for safety mask the reset enable */
pci_write_config_dword
(
ali_pci
,
0xCC
,
val
);
spin_unlock
(
&
ali_lock
);
}
/*
* ali_keepalive - send a keepalive to the watchdog
*
* Send a keepalive to the timer (actually we restart the timer).
*/
static
void
ali_keepalive
(
void
)
{
ali_start
();
}
/*
* ali_settimer - compute the timer reload value
* @t: time in seconds
*
* Computes the timeout values needed
*/
static
int
ali_settimer
(
int
t
)
{
if
(
t
<
0
)
return
-
EINVAL
;
else
if
(
t
<
60
)
ali_timeout_bits
=
t
|
(
1
<<
6
);
else
if
(
t
<
3600
)
ali_timeout_bits
=
(
t
/
60
)
|
(
1
<<
7
);
else
if
(
t
<
18000
)
ali_timeout_bits
=
(
t
/
300
)
|
(
1
<<
6
)
|
(
1
<<
7
);
else
return
-
EINVAL
;
timeout
=
t
;
return
0
;
}
/*
* /dev/watchdog handling
*/
/*
* ali_write - writes to ALi watchdog
* @file: file from VFS
* @data: user address of data
* @len: length of data
* @ppos: pointer to the file offset
*
* Handle a write to the ALi watchdog. Writing to the file pings
* the watchdog and resets it. Writing the magic 'V' sequence allows
* the next close to turn off the watchdog.
*/
static
ssize_t
ali_write
(
struct
file
*
file
,
const
char
*
data
,
size_t
len
,
loff_t
*
ppos
)
{
/* Can't seek (pwrite) on this device */
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
/* See if we got the magic character 'V' and reload the timer */
if
(
len
)
{
if
(
!
nowayout
)
{
size_t
i
;
/* note: just in case someone wrote the magic character
* five months ago... */
ali_expect_release
=
0
;
/* scan to see wether or not we got the magic character */
for
(
i
=
0
;
i
!=
len
;
i
++
)
{
char
c
;
if
(
get_user
(
c
,
data
+
i
))
return
-
EFAULT
;
if
(
c
==
'V'
)
ali_expect_release
=
42
;
}
}
/* someone wrote to us, we should reload the timer */
ali_start
();
}
return
len
;
}
/*
* ali_ioctl - handle watchdog ioctls
* @inode: VFS inode
* @file: VFS file pointer
* @cmd: ioctl number
* @arg: arguments to the ioctl
*
* Handle the watchdog ioctls supported by the ALi driver. Really
* we want an extension to enable irq ack monitoring and the like
*/
static
int
ali_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
static
struct
watchdog_info
ident
=
{
.
options
=
WDIOF_KEEPALIVEPING
|
WDIOF_SETTIMEOUT
|
WDIOF_MAGICCLOSE
,
.
firmware_version
=
0
,
.
identity
=
"ALi M1535 WatchDog Timer"
,
};
switch
(
cmd
)
{
case
WDIOC_GETSUPPORT
:
return
copy_to_user
((
struct
watchdog_info
*
)
arg
,
&
ident
,
sizeof
(
ident
))
?
-
EFAULT
:
0
;
case
WDIOC_GETSTATUS
:
case
WDIOC_GETBOOTSTATUS
:
return
put_user
(
0
,
(
int
*
)
arg
);
case
WDIOC_KEEPALIVE
:
ali_keepalive
();
return
0
;
case
WDIOC_SETOPTIONS
:
{
int
new_options
,
retval
=
-
EINVAL
;
if
(
get_user
(
new_options
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
new_options
&
WDIOS_DISABLECARD
)
{
ali_stop
();
retval
=
0
;
}
if
(
new_options
&
WDIOS_ENABLECARD
)
{
ali_start
();
retval
=
0
;
}
return
retval
;
}
case
WDIOC_SETTIMEOUT
:
{
int
new_timeout
;
if
(
get_user
(
new_timeout
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
ali_settimer
(
new_timeout
))
return
-
EINVAL
;
ali_keepalive
();
/* Fall */
}
case
WDIOC_GETTIMEOUT
:
return
put_user
(
timeout
,
(
int
*
)
arg
);
default:
return
-
ENOIOCTLCMD
;
}
}
/*
* ali_open - handle open of ali watchdog
* @inode: inode from VFS
* @file: file from VFS
*
* Open the ALi watchdog device. Ensure only one person opens it
* at a time. Also start the watchdog running.
*/
static
int
ali_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
/* /dev/watchdog can only be opened once */
if
(
test_and_set_bit
(
0
,
&
ali_is_open
))
return
-
EBUSY
;
/* Activate */
ali_start
();
return
0
;
}
/*
* ali_release - close an ALi watchdog
* @inode: inode from VFS
* @file: file from VFS
*
* Close the ALi watchdog device. Actual shutdown of the timer
* only occurs if the magic sequence has been set.
*/
static
int
ali_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
/*
* Shut off the timer.
*/
if
(
ali_expect_release
==
42
)
{
ali_stop
();
}
else
{
printk
(
KERN_CRIT
PFX
"Unexpected close, not stopping watchdog!
\n
"
);
ali_keepalive
();
}
clear_bit
(
0
,
&
ali_is_open
);
ali_expect_release
=
0
;
return
0
;
}
/*
* ali_notify_sys - System down notifier
*
* Notifier for system down
*/
static
int
ali_notify_sys
(
struct
notifier_block
*
this
,
unsigned
long
code
,
void
*
unused
)
{
if
(
code
==
SYS_DOWN
||
code
==
SYS_HALT
)
{
/* Turn the WDT off */
ali_stop
();
}
return
NOTIFY_DONE
;
}
/*
* Data for PCI driver interface
*
* This data only exists for exporting the supported
* PCI ids via MODULE_DEVICE_TABLE. We do not actually
* register a pci_driver, because someone else might one day
* want to register another driver on the same PCI id.
*/
static
struct
pci_device_id
ali_pci_tbl
[]
__initdata
=
{
{
PCI_VENDOR_ID_AL
,
1535
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
{
0
,
},
};
MODULE_DEVICE_TABLE
(
pci
,
ali_pci_tbl
);
/*
* ali_find_watchdog - find a 1535 and 7101
*
* Scans the PCI hardware for a 1535 series bridge and matching 7101
* watchdog device. This may be overtight but it is better to be safe
*/
static
int
__init
ali_find_watchdog
(
void
)
{
struct
pci_dev
*
pdev
;
u32
wdog
;
/* Check for a 1535 series bridge */
pdev
=
pci_find_device
(
PCI_VENDOR_ID_AL
,
0x1535
,
NULL
);
if
(
pdev
==
NULL
)
return
-
ENODEV
;
/* Check for the a 7101 PMU */
pdev
=
pci_find_device
(
PCI_VENDOR_ID_AL
,
0x7101
,
NULL
);
if
(
pdev
==
NULL
)
return
-
ENODEV
;
if
(
pci_enable_device
(
pdev
))
return
-
EIO
;
ali_pci
=
pdev
;
/*
* Initialize the timer bits
*/
pci_read_config_dword
(
pdev
,
0xCC
,
&
wdog
);
wdog
&=
~
0x3F
;
/* Timer bits */
wdog
&=
~
((
1
<<
27
)
|
(
1
<<
26
)
|
(
1
<<
25
)
|
(
1
<<
24
));
/* Issued events */
wdog
&=
~
((
1
<<
16
)
|
(
1
<<
13
)
|
(
1
<<
12
)
|
(
1
<<
11
)
|
(
1
<<
10
)
|
(
1
<<
9
));
/* No monitor bits */
pci_write_config_dword
(
pdev
,
0xCC
,
wdog
);
return
0
;
}
/*
* Kernel Interfaces
*/
static
struct
file_operations
ali_fops
=
{
.
owner
=
THIS_MODULE
,
.
llseek
=
no_llseek
,
.
write
=
ali_write
,
.
ioctl
=
ali_ioctl
,
.
open
=
ali_open
,
.
release
=
ali_release
,
};
static
struct
miscdevice
ali_miscdev
=
{
.
minor
=
WATCHDOG_MINOR
,
.
name
=
"watchdog"
,
.
fops
=
&
ali_fops
,
};
static
struct
notifier_block
ali_notifier
=
{
.
notifier_call
=
ali_notify_sys
,
.
next
=
NULL
,
.
priority
=
0
,
};
/*
* watchdog_init - module initialiser
*
* Scan for a suitable watchdog and if so initialize it. Return an error
* if we cannot, the error causes the module to unload
*/
static
int
__init
watchdog_init
(
void
)
{
int
ret
;
spin_lock_init
(
&
ali_lock
);
/* Check wether or not the hardware watchdog is there */
if
(
ali_find_watchdog
()
!=
0
)
{
return
-
ENODEV
;
}
/* Check that the timeout value is within it's range ; if not reset to the default */
if
(
timeout
<
1
||
timeout
>=
18000
)
{
timeout
=
WATCHDOG_TIMEOUT
;
printk
(
KERN_INFO
PFX
"timeout value must be 0<timeout<18000, using %d
\n
"
,
timeout
);
}
/* Calculate the watchdog's timeout */
ali_settimer
(
timeout
);
ret
=
misc_register
(
&
ali_miscdev
);
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
PFX
"cannot register miscdev on minor=%d (err=%d)
\n
"
,
WATCHDOG_MINOR
,
ret
);
goto
out
;
}
ret
=
register_reboot_notifier
(
&
ali_notifier
);
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
PFX
"cannot register reboot notifier (err=%d)
\n
"
,
ret
);
goto
unreg_miscdev
;
}
printk
(
KERN_INFO
PFX
"initialized. timeout=%d sec (nowayout=%d)
\n
"
,
timeout
,
nowayout
);
out:
return
ret
;
unreg_miscdev:
misc_deregister
(
&
ali_miscdev
);
goto
out
;
}
/*
* watchdog_exit - module de-initialiser
*
* Called while unloading a successfully installed watchdog module.
*/
static
void
__exit
watchdog_exit
(
void
)
{
/* Stop the timer before we leave */
ali_stop
();
/* Deregister */
unregister_reboot_notifier
(
&
ali_notifier
);
misc_deregister
(
&
ali_miscdev
);
}
module_init
(
watchdog_init
);
module_exit
(
watchdog_exit
);
MODULE_AUTHOR
(
"Alan Cox"
);
MODULE_DESCRIPTION
(
"ALi M1535 PMU Watchdog Timer driver"
);
MODULE_LICENSE
(
"GPL"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment