aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/watchdog/shwdt.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-09-27 04:53:59 -0400
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 04:53:59 -0400
commitf118420be83c3ce7888fe1d42db84af495da9edb (patch)
tree5d6bf59f2d9dee6623a63cd51a56a806b73d81d0 /drivers/char/watchdog/shwdt.c
parent781125ca58dfbd47635cfc0e408f1f9d7e10b227 (diff)
watchdog: Add a simple mmap() stub for shwdt.
In some applications people have expressed a need for an mmap() method, so we implement a simple stub for this that maps back a page with the counter in it. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/char/watchdog/shwdt.c')
-rw-r--r--drivers/char/watchdog/shwdt.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c
index 7c39f39effdf..e5b8c64f1d65 100644
--- a/drivers/char/watchdog/shwdt.c
+++ b/drivers/char/watchdog/shwdt.c
@@ -27,7 +27,7 @@
27#include <linux/notifier.h> 27#include <linux/notifier.h>
28#include <linux/ioport.h> 28#include <linux/ioport.h>
29#include <linux/fs.h> 29#include <linux/fs.h>
30 30#include <linux/mm.h>
31#include <asm/io.h> 31#include <asm/io.h>
32#include <asm/uaccess.h> 32#include <asm/uaccess.h>
33#include <asm/watchdog.h> 33#include <asm/watchdog.h>
@@ -258,6 +258,55 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf,
258} 258}
259 259
260/** 260/**
261 * sh_wdt_mmap - map WDT/CPG registers into userspace
262 * @file: file structure for the device
263 * @vma: VMA to map the registers into
264 *
265 * A simple mmap() implementation for the corner cases where the counter
266 * needs to be mapped in userspace directly. Due to the relatively small
267 * size of the area, neighbouring registers not necessarily tied to the
268 * CPG will also be accessible through the register page, so this remains
269 * configurable for users that really know what they're doing.
270 *
271 * Additionaly, the register page maps in the CPG register base relative
272 * to the nearest page-aligned boundary, which requires that userspace do
273 * the appropriate CPU subtype math for calculating the page offset for
274 * the counter value.
275 */
276static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
277{
278 int ret = -ENOSYS;
279
280#ifdef CONFIG_SH_WDT_MMAP
281 unsigned long addr;
282
283 /* Only support the simple cases where we map in a register page. */
284 if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
285 return -EINVAL;
286
287 /*
288 * Pick WTCNT as the start, it's usually the first register after the
289 * FRQCR, and neither one are generally page-aligned out of the box.
290 */
291 addr = WTCNT & ~(PAGE_SIZE - 1);
292
293 vma->vm_flags |= VM_IO;
294 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
295
296 if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
297 PAGE_SIZE, vma->vm_page_prot)) {
298 printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
299 __FUNCTION__);
300 return -EAGAIN;
301 }
302
303 ret = 0;
304#endif
305
306 return ret;
307}
308
309/**
261 * sh_wdt_ioctl - Query Device 310 * sh_wdt_ioctl - Query Device
262 * @inode: inode of device 311 * @inode: inode of device
263 * @file: file handle of device 312 * @file: file handle of device
@@ -342,6 +391,7 @@ static const struct file_operations sh_wdt_fops = {
342 .ioctl = sh_wdt_ioctl, 391 .ioctl = sh_wdt_ioctl,
343 .open = sh_wdt_open, 392 .open = sh_wdt_open,
344 .release = sh_wdt_close, 393 .release = sh_wdt_close,
394 .mmap = sh_wdt_mmap,
345}; 395};
346 396
347static struct watchdog_info sh_wdt_info = { 397static struct watchdog_info sh_wdt_info = {