aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Mayer <markus.mayer@linaro.org>2013-11-25 13:57:47 -0800
committerMarkus Mayer <markus.mayer@linaro.org>2013-11-28 16:35:18 -0800
commitbedb7cfd6328f52ba2d994e5e1d5c2cd9a707834 (patch)
tree443f69725c77361045d7bdfe61bb72d59ea357d0
parenta82e2f76bc57cca37db107e49541e137a072c155 (diff)
watchdog: bcm281xx: Support for timer resolution ioctlsrfc/watchdog-resolution
This change makes use of the watchdog timer resolution support that is present in the watchdog framework. It depends on the following patch series: http://www.spinics.net/lists/linux-watchdog/msg03328.html A userland application can set or retrieve the watchdog timer's resolution using code like this: /* Set the watchdog timer resolution */ resolution = ... ; printf("setting watchdog timer resolution to %d\n", resolution); ret = ioctl(fd, WDIOC_SETRESOLUTION, &resolution); if (ret < 0) fprintf(stderr, "%s: ioctl failed -- %s\n", prg, strerror(errno)); /* Retrieve the watchdog timer resolution */ ret = ioctl(fd, WDIOC_GETRESOLUTION, &resolution); if (ret < 0) fprintf(stderr, "%s: ioctl failed -- %s\n", prg, strerror(errno)); else printf("resolution: %d\n",resolution); break;
-rw-r--r--drivers/watchdog/bcm_kona_wdt.c57
1 files changed, 31 insertions, 26 deletions
diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c
index 9fe174b28db..30e4e9bcbb1 100644
--- a/drivers/watchdog/bcm_kona_wdt.c
+++ b/drivers/watchdog/bcm_kona_wdt.c
@@ -54,7 +54,6 @@ struct bcm_kona_wdt {
* us a maximum of about 18 hours and 12 minutes before the watchdog
* times out.
*/
- int resolution;
spinlock_t lock;
#ifdef CONFIG_BCM_KONA_WDT_DEBUG
struct dentry *debugfs;
@@ -104,9 +103,10 @@ static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data)
{
int ctl_val, cur_val, ret;
unsigned long flags;
- struct bcm_kona_wdt *wdt = s->private;
+ struct watchdog_device *wdd = s->private;
+ struct bcm_kona_wdt *wdt = watchdog_get_drvdata(wdd);
- if (!wdt)
+ if (!wdd || !wdt)
return seq_puts(s, "No device pointer\n");
spin_lock_irqsave(&wdt->lock, flags);
@@ -122,13 +122,13 @@ static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data)
ctl = ctl_val & SECWDOG_COUNT_MASK;
res = (ctl_val & SECWDOG_RES_MASK) >> SECWDOG_CLKS_SHIFT;
cur = cur_val & SECWDOG_COUNT_MASK;
- ctl_sec = TICKS_TO_SECS(ctl, wdt);
- cur_sec = TICKS_TO_SECS(cur, wdt);
+ ctl_sec = TICKS_TO_SECS(ctl, wdd);
+ cur_sec = TICKS_TO_SECS(cur, wdd);
ret = seq_printf(s, "Resolution: %d / %d\n"
"Control: %d s / %d (%#x) ticks\n"
"Current: %d s / %d (%#x) ticks\n"
"Busy count: %lu\n", res,
- wdt->resolution, ctl_sec, ctl, ctl, cur_sec,
+ wdd->resolution, ctl_sec, ctl, ctl, cur_sec,
cur, cur, busy_count);
}
@@ -156,7 +156,7 @@ static struct dentry *bcm_kona_wdt_debugfs_init(struct bcm_kona_wdt *wdt,
if (IS_ERR_OR_NULL(dir))
return NULL;
- if (debugfs_create_file("info", S_IFREG | S_IRUGO, dir, wdt,
+ if (debugfs_create_file("info", S_IFREG | S_IRUGO, dir, wdd,
&bcm_kona_dbg_operations))
return dir;
@@ -195,13 +195,14 @@ static int bcm_kona_wdt_ctrl_reg_modify(struct bcm_kona_wdt *wdt,
return ret;
}
-static int bcm_kona_wdt_set_resolution_reg(struct bcm_kona_wdt *wdt)
+static int bcm_kona_wdt_set_resolution(struct watchdog_device *wdog,
+ unsigned r)
{
- if (wdt->resolution > SECWDOG_MAX_RES)
- return -EINVAL;
+ struct bcm_kona_wdt *wdt = watchdog_get_drvdata(wdog);
+ wdog->resolution = r;
return bcm_kona_wdt_ctrl_reg_modify(wdt, SECWDOG_RES_MASK,
- wdt->resolution << SECWDOG_CLKS_SHIFT);
+ r << SECWDOG_CLKS_SHIFT);
}
static int bcm_kona_wdt_set_timeout_reg(struct watchdog_device *wdog,
@@ -210,7 +211,7 @@ static int bcm_kona_wdt_set_timeout_reg(struct watchdog_device *wdog,
struct bcm_kona_wdt *wdt = watchdog_get_drvdata(wdog);
return bcm_kona_wdt_ctrl_reg_modify(wdt, SECWDOG_COUNT_MASK,
- SECS_TO_TICKS(wdog->timeout, wdt) |
+ SECS_TO_TICKS(wdog->timeout, wdog) |
watchdog_flags);
}
@@ -234,7 +235,7 @@ static unsigned int bcm_kona_wdt_get_timeleft(struct watchdog_device *wdog)
if (val < 0)
return val;
- return TICKS_TO_SECS(val & SECWDOG_COUNT_MASK, wdt);
+ return TICKS_TO_SECS(val & SECWDOG_COUNT_MASK, wdog);
}
static int bcm_kona_wdt_start(struct watchdog_device *wdog)
@@ -252,16 +253,17 @@ static int bcm_kona_wdt_stop(struct watchdog_device *wdog)
}
static struct watchdog_ops bcm_kona_wdt_ops = {
- .owner = THIS_MODULE,
- .start = bcm_kona_wdt_start,
- .stop = bcm_kona_wdt_stop,
- .set_timeout = bcm_kona_wdt_set_timeout,
- .get_timeleft = bcm_kona_wdt_get_timeleft,
+ .owner = THIS_MODULE,
+ .start = bcm_kona_wdt_start,
+ .stop = bcm_kona_wdt_stop,
+ .set_timeout = bcm_kona_wdt_set_timeout,
+ .get_timeleft = bcm_kona_wdt_get_timeleft,
+ .set_resolution = bcm_kona_wdt_set_resolution,
};
static struct watchdog_info bcm_kona_wdt_info = {
- .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
- WDIOF_KEEPALIVEPING,
+ .options = WDIOF_SETTIMEOUT | WDIOF_SETRESOLUTION |
+ WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
.identity = "Broadcom Kona Watchdog Timer",
};
@@ -271,6 +273,9 @@ static struct watchdog_device bcm_kona_wdt_wdd = {
.min_timeout = 1,
.max_timeout = SECWDOG_MAX_COUNT >> SECWDOG_DEFAULT_RESOLUTION,
.timeout = SECWDOG_MAX_COUNT >> SECWDOG_DEFAULT_RESOLUTION,
+ .min_resolution = 0,
+ .max_resolution = SECWDOG_MAX_RES,
+ .resolution = SECWDOG_DEFAULT_RESOLUTION
};
static void bcm_kona_wdt_shutdown(struct platform_device *pdev)
@@ -294,17 +299,17 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev)
if (IS_ERR(wdt->base))
return -ENODEV;
- wdt->resolution = SECWDOG_DEFAULT_RESOLUTION;
- ret = bcm_kona_wdt_set_resolution_reg(wdt);
+ spin_lock_init(&wdt->lock);
+ platform_set_drvdata(pdev, wdt);
+ watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt);
+
+ ret = bcm_kona_wdt_set_resolution(&bcm_kona_wdt_wdd,
+ bcm_kona_wdt_wdd.resolution);
if (ret) {
dev_err(dev, "Failed to set resolution (error: %d)", ret);
return ret;
}
- spin_lock_init(&wdt->lock);
- platform_set_drvdata(pdev, wdt);
- watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt);
-
ret = bcm_kona_wdt_set_timeout_reg(&bcm_kona_wdt_wdd, 0);
if (ret) {
dev_err(dev, "Failed set watchdog timeout");