[RFC 2/2] watchdog: bcm281xx: Support for timer resolution ioctls

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
---
 drivers/watchdog/bcm_kona_wdt.c |   57 +++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 26 deletions(-)

diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c
index 9fe174b..30e4e9b 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");
-- 
1.7.9.5


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




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux