All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Arlott <simon@fire.lp0.eu>
To: Guenter Roeck <linux@roeck-us.net>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	Ralf Baechle <ralf@linux-mips.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Jason Cooper <jason@lakedaemon.net>,
	Marc Zyngier <marc.zyngier@arm.com>,
	Kevin Cernekee <cernekee@gmail.com>,
	Florian Fainelli <f.fainelli@gmail.com>,
	Wim Van Sebroeck <wim@iguana.be>,
	Maxime Bizon <mbizon@freebox.fr>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	linux-mips@linux-mips.org, linux-watchdog@vger.kernel.org
Cc: Rob Herring <robh+dt@kernel.org>, Pawel Moll <pawel.moll@arm.com>,
	Mark Rutland <mark.rutland@arm.com>,
	Ian Campbell <ijc+devicetree@hellion.org.uk>,
	Kumar Gala <galak@codeaurora.org>,
	Jonas Gorski <jogo@openwrt.org>
Subject: [PATCH (v3) 5/11] watchdog: bcm63xx_wdt: Use WATCHDOG_CORE
Date: Wed, 25 Nov 2015 22:40:41 +0000	[thread overview]
Message-ID: <565638E9.3010304@simon.arlott.org.uk> (raw)
In-Reply-To: <56552099.7070709@roeck-us.net>

Convert bcm63xx_wdt to use WATCHDOG_CORE.

The default and maximum time constants that are only used once have been
moved to the initialisation of the struct watchdog_device.

Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
---
Patch 7 split into two patches.

On 25/11/15 02:44, Guenter Roeck wrote:
> If I see correctly, there is no ping function. In that case, the watchdog core
> will call the start function after updating the timeout, so there is no need
> to do it here.

Fixed.
 
>> +static const struct watchdog_info bcm63xx_wdt_info = {
>> +	.options = WDIOC_GETTIMELEFT | WDIOF_SETTIMEOUT |
> 
> Where is the gettimeleft function ? I think you are adding it with a later patch,
> but then you should set the flag there, not here.

Removed WDIOC_GETTIMELEFT completely because it's not a flag.

>> +	hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
>> +	wdd = devm_kzalloc(&pdev->dev, sizeof(*wdd), GFP_KERNEL);
> 
> It would be better to allocate wdd as part of struct bcm63xx_wdt_hw.

Fixed.

>> -	misc_deregister(&bcm63xx_wdt_miscdev);
>>   	bcm63xx_timer_unregister(TIMER_WDT_ID);
>> +	watchdog_unregister_device(wdd);
> 
> Shouldn't that come first, before unregistering the timer ?

No, because wdd->dev is used in the interrupt handler. The handler will
not be called after bcm63xx_timer_unregister() is called.

Moved registration of the timer in the probe function to after register
of the watchdog device because the interrupt handler uses wdd->dev.

 drivers/watchdog/Kconfig       |   1 +
 drivers/watchdog/bcm63xx_wdt.c | 259 +++++++++++++----------------------------
 2 files changed, 79 insertions(+), 181 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7a8a6c6..6815b74 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1273,6 +1273,7 @@ config OCTEON_WDT
 config BCM63XX_WDT
 	tristate "Broadcom BCM63xx hardware watchdog"
 	depends on BCM63XX
+	select WATCHDOG_CORE
 	help
 	  Watchdog driver for the built in watchdog hardware in Broadcom
 	  BCM63xx SoC.
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 3f55cba..2257924 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -13,20 +13,15 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/bitops.h>
 #include <linux/errno.h>
-#include <linux/fs.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
-#include <linux/uaccess.h>
 #include <linux/watchdog.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 #include <linux/resource.h>
 #include <linux/platform_device.h>
 
@@ -38,53 +33,59 @@
 #define PFX KBUILD_MODNAME
 
 #define WDT_HZ			50000000		/* Fclk */
-#define WDT_DEFAULT_TIME	30			/* seconds */
-#define WDT_MAX_TIME		(0xffffffff / WDT_HZ)	/* seconds */
 
 struct bcm63xx_wdt_hw {
+	struct watchdog_device wdd;
 	raw_spinlock_t lock;
 	void __iomem *regs;
-	unsigned long inuse;
 	bool running;
 };
-static struct bcm63xx_wdt_hw bcm63xx_wdt_device;
 
-static int expect_close;
+#define to_wdt_hw(x) container_of(x, struct bcm63xx_wdt_hw, wdd)
 
-static int wdt_time = WDT_DEFAULT_TIME;
 static bool nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
 	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-/* HW functions */
-static void bcm63xx_wdt_hw_start(void)
+static int bcm63xx_wdt_start(struct watchdog_device *wdd)
 {
+	struct bcm63xx_wdt_hw *hw = to_wdt_hw(wdd);
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&bcm63xx_wdt_device.lock, flags);
-	bcm_writel(wdt_time * WDT_HZ, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG);
-	bcm_writel(WDT_START_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-	bcm_writel(WDT_START_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-	bcm63xx_wdt_device.running = true;
-	raw_spin_unlock_irqrestore(&bcm63xx_wdt_device.lock, flags);
+	raw_spin_lock_irqsave(&hw->lock, flags);
+	bcm_writel(wdd->timeout * WDT_HZ, hw->regs + WDT_DEFVAL_REG);
+	bcm_writel(WDT_START_1, hw->regs + WDT_CTL_REG);
+	bcm_writel(WDT_START_2, hw->regs + WDT_CTL_REG);
+	hw->running = true;
+	raw_spin_unlock_irqrestore(&hw->lock, flags);
+	return 0;
 }
 
-static void bcm63xx_wdt_hw_stop(void)
+static int bcm63xx_wdt_stop(struct watchdog_device *wdd)
 {
+	struct bcm63xx_wdt_hw *hw = to_wdt_hw(wdd);
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&bcm63xx_wdt_device.lock, flags);
-	bcm_writel(WDT_STOP_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-	bcm_writel(WDT_STOP_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-	bcm63xx_wdt_device.running = false;
-	raw_spin_unlock_irqrestore(&bcm63xx_wdt_device.lock, flags);
+	raw_spin_lock_irqsave(&hw->lock, flags);
+	bcm_writel(WDT_STOP_1, hw->regs + WDT_CTL_REG);
+	bcm_writel(WDT_STOP_2, hw->regs + WDT_CTL_REG);
+	hw->running = false;
+	raw_spin_unlock_irqrestore(&hw->lock, flags);
+	return 0;
+}
+
+static int bcm63xx_wdt_set_timeout(struct watchdog_device *wdd,
+	unsigned int timeout)
+{
+	wdd->timeout = timeout;
+	return 0;
 }
 
 /* The watchdog interrupt occurs when half the timeout is remaining */
 static void bcm63xx_wdt_isr(void *data)
 {
-	struct bcm63xx_wdt_hw *hw = &bcm63xx_wdt_device;
+	struct bcm63xx_wdt_hw *hw = data;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&hw->lock, flags);
@@ -118,147 +119,36 @@ static void bcm63xx_wdt_isr(void *data)
 		}
 
 		ms = timeleft / (WDT_HZ / 1000);
-		pr_alert("warning timer fired, reboot in %ums\n", ms);
+		dev_alert(hw->wdd.dev,
+			"warning timer fired, reboot in %ums\n", ms);
 	}
 	raw_spin_unlock_irqrestore(&hw->lock, flags);
 }
 
-static int bcm63xx_wdt_settimeout(int new_time)
-{
-	if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
-		return -EINVAL;
-
-	wdt_time = new_time;
-
-	return 0;
-}
-
-static int bcm63xx_wdt_open(struct inode *inode, struct file *file)
-{
-	if (test_and_set_bit(0, &bcm63xx_wdt_device.inuse))
-		return -EBUSY;
-
-	bcm63xx_wdt_hw_start();
-	return nonseekable_open(inode, file);
-}
-
-static int bcm63xx_wdt_release(struct inode *inode, struct file *file)
-{
-	if (expect_close == 42)
-		bcm63xx_wdt_hw_stop();
-	else {
-		pr_crit("Unexpected close, not stopping watchdog!\n");
-		bcm63xx_wdt_hw_start();
-	}
-	clear_bit(0, &bcm63xx_wdt_device.inuse);
-	expect_close = 0;
-	return 0;
-}
-
-static ssize_t bcm63xx_wdt_write(struct file *file, const char *data,
-				size_t len, loff_t *ppos)
-{
-	if (len) {
-		if (!nowayout) {
-			size_t i;
-
-			/* In case it was set long ago */
-			expect_close = 0;
-
-			for (i = 0; i != len; i++) {
-				char c;
-				if (get_user(c, data + i))
-					return -EFAULT;
-				if (c == 'V')
-					expect_close = 42;
-			}
-		}
-		bcm63xx_wdt_hw_start();
-	}
-	return len;
-}
-
-static struct watchdog_info bcm63xx_wdt_info = {
-	.identity       = PFX,
-	.options        = WDIOF_SETTIMEOUT |
-				WDIOF_KEEPALIVEPING |
-				WDIOF_MAGICCLOSE,
+static struct watchdog_ops bcm63xx_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = bcm63xx_wdt_start,
+	.stop = bcm63xx_wdt_stop,
+	.set_timeout = bcm63xx_wdt_set_timeout,
 };
 
-
-static long bcm63xx_wdt_ioctl(struct file *file, unsigned int cmd,
-				unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-	int new_value, retval = -EINVAL;
-
-	switch (cmd) {
-	case WDIOC_GETSUPPORT:
-		return copy_to_user(argp, &bcm63xx_wdt_info,
-			sizeof(bcm63xx_wdt_info)) ? -EFAULT : 0;
-
-	case WDIOC_GETSTATUS:
-	case WDIOC_GETBOOTSTATUS:
-		return put_user(0, p);
-
-	case WDIOC_SETOPTIONS:
-		if (get_user(new_value, p))
-			return -EFAULT;
-
-		if (new_value & WDIOS_DISABLECARD) {
-			bcm63xx_wdt_hw_stop();
-			retval = 0;
-		}
-		if (new_value & WDIOS_ENABLECARD) {
-			bcm63xx_wdt_hw_start();
-			retval = 0;
-		}
-
-		return retval;
-
-	case WDIOC_KEEPALIVE:
-		bcm63xx_wdt_hw_start();
-		return 0;
-
-	case WDIOC_SETTIMEOUT:
-		if (get_user(new_value, p))
-			return -EFAULT;
-
-		if (bcm63xx_wdt_settimeout(new_value))
-			return -EINVAL;
-
-		bcm63xx_wdt_hw_start();
-
-	case WDIOC_GETTIMEOUT:
-		return put_user(wdt_time, p);
-
-	default:
-		return -ENOTTY;
-
-	}
-}
-
-static const struct file_operations bcm63xx_wdt_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.write		= bcm63xx_wdt_write,
-	.unlocked_ioctl	= bcm63xx_wdt_ioctl,
-	.open		= bcm63xx_wdt_open,
-	.release	= bcm63xx_wdt_release,
-};
-
-static struct miscdevice bcm63xx_wdt_miscdev = {
-	.minor	= WATCHDOG_MINOR,
-	.name	= "watchdog",
-	.fops	= &bcm63xx_wdt_fops,
+static const struct watchdog_info bcm63xx_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.identity = "BCM63xx Watchdog",
 };
 
-
 static int bcm63xx_wdt_probe(struct platform_device *pdev)
 {
-	int ret;
+	struct bcm63xx_wdt_hw *hw;
+	struct watchdog_device *wdd;
 	struct resource *r;
+	int ret;
+
+	hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
+	if (!hw)
+		return -ENOMEM;
+
+	wdd = &hw->wdd;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
@@ -266,58 +156,65 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	bcm63xx_wdt_device.regs = devm_ioremap_nocache(&pdev->dev, r->start,
-							resource_size(r));
-	if (!bcm63xx_wdt_device.regs) {
+	hw->regs = devm_ioremap_nocache(&pdev->dev, r->start, resource_size(r));
+	if (!hw->regs) {
 		dev_err(&pdev->dev, "failed to remap I/O resources\n");
 		return -ENXIO;
 	}
 
-	raw_spin_lock_init(&bcm63xx_wdt_device.lock);
-	bcm63xx_wdt_device.running = false;
+	raw_spin_lock_init(&hw->lock);
+	hw->running = false;
 
-	ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, NULL);
+	wdd->parent = &pdev->dev;
+	wdd->ops = &bcm63xx_wdt_ops;
+	wdd->info = &bcm63xx_wdt_info;
+	wdd->min_timeout = 1;
+	wdd->max_timeout = 0xffffffff / WDT_HZ;
+	wdd->timeout = min(30U, wdd->max_timeout);
+
+	platform_set_drvdata(pdev, hw);
+
+	watchdog_init_timeout(wdd, 0, &pdev->dev);
+	watchdog_set_nowayout(wdd, nowayout);
+
+	ret = watchdog_register_device(wdd);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to register wdt timer isr\n");
+		dev_err(&pdev->dev, "failed to register watchdog device\n");
 		return ret;
 	}
 
-	if (bcm63xx_wdt_settimeout(wdt_time)) {
-		bcm63xx_wdt_settimeout(WDT_DEFAULT_TIME);
-		dev_info(&pdev->dev,
-			": wdt_time value must be 1 <= wdt_time <= %d, using %d\n",
-			WDT_MAX_TIME, wdt_time);
-	}
-
-	ret = misc_register(&bcm63xx_wdt_miscdev);
+	ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, hw);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to register watchdog device\n");
-		goto unregister_timer;
+		dev_err(&pdev->dev, "failed to register wdt timer isr\n");
+		goto unregister_watchdog;
 	}
 
-	dev_info(&pdev->dev, " started, timer margin: %d sec\n",
-						WDT_DEFAULT_TIME);
+	dev_info(&pdev->dev,
+		"%s at MMIO 0x%p (timeout = %us, max_timeout = %us)",
+		dev_name(wdd->dev), hw->regs,
+		wdd->timeout, wdd->max_timeout);
 
 	return 0;
 
-unregister_timer:
-	bcm63xx_timer_unregister(TIMER_WDT_ID);
+unregister_watchdog:
+	watchdog_unregister_device(wdd);
 	return ret;
 }
 
 static int bcm63xx_wdt_remove(struct platform_device *pdev)
 {
-	if (!nowayout)
-		bcm63xx_wdt_hw_stop();
+	struct bcm63xx_wdt_hw *hw = platform_get_drvdata(pdev);
 
-	misc_deregister(&bcm63xx_wdt_miscdev);
 	bcm63xx_timer_unregister(TIMER_WDT_ID);
+	watchdog_unregister_device(&hw->wdd);
 	return 0;
 }
 
 static void bcm63xx_wdt_shutdown(struct platform_device *pdev)
 {
-	bcm63xx_wdt_hw_stop();
+	struct bcm63xx_wdt_hw *hw = platform_get_drvdata(pdev);
+
+	bcm63xx_wdt_stop(&hw->wdd);
 }
 
 static struct platform_driver bcm63xx_wdt_driver = {
-- 
2.1.4

-- 
Simon Arlott

WARNING: multiple messages have this Message-ID (diff)
From: Simon Arlott <simon-A6De1vDTPLDsq35pWSNszA@public.gmane.org>
To: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>,
	"devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
	<devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>,
	Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>,
	Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>,
	Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>,
	Kevin Cernekee <cernekee-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	Florian Fainelli
	<f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	Wim Van Sebroeck <wim-IQzOog9fTRqzQB+pC5nmwQ@public.gmane.org>,
	Maxime Bizon <mbizon-MmRyKUhfbQ9GWvitb5QawA@public.gmane.org>,
	Linux Kernel Mailing List
	<linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	linux-mips-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>,
	Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
	Ian Campbell
	<ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org>,
	Kumar Gala <galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>,
	Jonas Gorski <jogo-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
Subject: [PATCH (v3) 5/11] watchdog: bcm63xx_wdt: Use WATCHDOG_CORE
Date: Wed, 25 Nov 2015 22:40:41 +0000	[thread overview]
Message-ID: <565638E9.3010304@simon.arlott.org.uk> (raw)
In-Reply-To: <56552099.7070709-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>

Convert bcm63xx_wdt to use WATCHDOG_CORE.

The default and maximum time constants that are only used once have been
moved to the initialisation of the struct watchdog_device.

Signed-off-by: Simon Arlott <simon-A6De1vDTPLDsq35pWSNszA@public.gmane.org>
---
Patch 7 split into two patches.

On 25/11/15 02:44, Guenter Roeck wrote:
> If I see correctly, there is no ping function. In that case, the watchdog core
> will call the start function after updating the timeout, so there is no need
> to do it here.

Fixed.
 
>> +static const struct watchdog_info bcm63xx_wdt_info = {
>> +	.options = WDIOC_GETTIMELEFT | WDIOF_SETTIMEOUT |
> 
> Where is the gettimeleft function ? I think you are adding it with a later patch,
> but then you should set the flag there, not here.

Removed WDIOC_GETTIMELEFT completely because it's not a flag.

>> +	hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
>> +	wdd = devm_kzalloc(&pdev->dev, sizeof(*wdd), GFP_KERNEL);
> 
> It would be better to allocate wdd as part of struct bcm63xx_wdt_hw.

Fixed.

>> -	misc_deregister(&bcm63xx_wdt_miscdev);
>>   	bcm63xx_timer_unregister(TIMER_WDT_ID);
>> +	watchdog_unregister_device(wdd);
> 
> Shouldn't that come first, before unregistering the timer ?

No, because wdd->dev is used in the interrupt handler. The handler will
not be called after bcm63xx_timer_unregister() is called.

Moved registration of the timer in the probe function to after register
of the watchdog device because the interrupt handler uses wdd->dev.

 drivers/watchdog/Kconfig       |   1 +
 drivers/watchdog/bcm63xx_wdt.c | 259 +++++++++++++----------------------------
 2 files changed, 79 insertions(+), 181 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7a8a6c6..6815b74 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1273,6 +1273,7 @@ config OCTEON_WDT
 config BCM63XX_WDT
 	tristate "Broadcom BCM63xx hardware watchdog"
 	depends on BCM63XX
+	select WATCHDOG_CORE
 	help
 	  Watchdog driver for the built in watchdog hardware in Broadcom
 	  BCM63xx SoC.
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 3f55cba..2257924 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -13,20 +13,15 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/bitops.h>
 #include <linux/errno.h>
-#include <linux/fs.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
-#include <linux/uaccess.h>
 #include <linux/watchdog.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 #include <linux/resource.h>
 #include <linux/platform_device.h>
 
@@ -38,53 +33,59 @@
 #define PFX KBUILD_MODNAME
 
 #define WDT_HZ			50000000		/* Fclk */
-#define WDT_DEFAULT_TIME	30			/* seconds */
-#define WDT_MAX_TIME		(0xffffffff / WDT_HZ)	/* seconds */
 
 struct bcm63xx_wdt_hw {
+	struct watchdog_device wdd;
 	raw_spinlock_t lock;
 	void __iomem *regs;
-	unsigned long inuse;
 	bool running;
 };
-static struct bcm63xx_wdt_hw bcm63xx_wdt_device;
 
-static int expect_close;
+#define to_wdt_hw(x) container_of(x, struct bcm63xx_wdt_hw, wdd)
 
-static int wdt_time = WDT_DEFAULT_TIME;
 static bool nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
 	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-/* HW functions */
-static void bcm63xx_wdt_hw_start(void)
+static int bcm63xx_wdt_start(struct watchdog_device *wdd)
 {
+	struct bcm63xx_wdt_hw *hw = to_wdt_hw(wdd);
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&bcm63xx_wdt_device.lock, flags);
-	bcm_writel(wdt_time * WDT_HZ, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG);
-	bcm_writel(WDT_START_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-	bcm_writel(WDT_START_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-	bcm63xx_wdt_device.running = true;
-	raw_spin_unlock_irqrestore(&bcm63xx_wdt_device.lock, flags);
+	raw_spin_lock_irqsave(&hw->lock, flags);
+	bcm_writel(wdd->timeout * WDT_HZ, hw->regs + WDT_DEFVAL_REG);
+	bcm_writel(WDT_START_1, hw->regs + WDT_CTL_REG);
+	bcm_writel(WDT_START_2, hw->regs + WDT_CTL_REG);
+	hw->running = true;
+	raw_spin_unlock_irqrestore(&hw->lock, flags);
+	return 0;
 }
 
-static void bcm63xx_wdt_hw_stop(void)
+static int bcm63xx_wdt_stop(struct watchdog_device *wdd)
 {
+	struct bcm63xx_wdt_hw *hw = to_wdt_hw(wdd);
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&bcm63xx_wdt_device.lock, flags);
-	bcm_writel(WDT_STOP_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-	bcm_writel(WDT_STOP_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-	bcm63xx_wdt_device.running = false;
-	raw_spin_unlock_irqrestore(&bcm63xx_wdt_device.lock, flags);
+	raw_spin_lock_irqsave(&hw->lock, flags);
+	bcm_writel(WDT_STOP_1, hw->regs + WDT_CTL_REG);
+	bcm_writel(WDT_STOP_2, hw->regs + WDT_CTL_REG);
+	hw->running = false;
+	raw_spin_unlock_irqrestore(&hw->lock, flags);
+	return 0;
+}
+
+static int bcm63xx_wdt_set_timeout(struct watchdog_device *wdd,
+	unsigned int timeout)
+{
+	wdd->timeout = timeout;
+	return 0;
 }
 
 /* The watchdog interrupt occurs when half the timeout is remaining */
 static void bcm63xx_wdt_isr(void *data)
 {
-	struct bcm63xx_wdt_hw *hw = &bcm63xx_wdt_device;
+	struct bcm63xx_wdt_hw *hw = data;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&hw->lock, flags);
@@ -118,147 +119,36 @@ static void bcm63xx_wdt_isr(void *data)
 		}
 
 		ms = timeleft / (WDT_HZ / 1000);
-		pr_alert("warning timer fired, reboot in %ums\n", ms);
+		dev_alert(hw->wdd.dev,
+			"warning timer fired, reboot in %ums\n", ms);
 	}
 	raw_spin_unlock_irqrestore(&hw->lock, flags);
 }
 
-static int bcm63xx_wdt_settimeout(int new_time)
-{
-	if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
-		return -EINVAL;
-
-	wdt_time = new_time;
-
-	return 0;
-}
-
-static int bcm63xx_wdt_open(struct inode *inode, struct file *file)
-{
-	if (test_and_set_bit(0, &bcm63xx_wdt_device.inuse))
-		return -EBUSY;
-
-	bcm63xx_wdt_hw_start();
-	return nonseekable_open(inode, file);
-}
-
-static int bcm63xx_wdt_release(struct inode *inode, struct file *file)
-{
-	if (expect_close == 42)
-		bcm63xx_wdt_hw_stop();
-	else {
-		pr_crit("Unexpected close, not stopping watchdog!\n");
-		bcm63xx_wdt_hw_start();
-	}
-	clear_bit(0, &bcm63xx_wdt_device.inuse);
-	expect_close = 0;
-	return 0;
-}
-
-static ssize_t bcm63xx_wdt_write(struct file *file, const char *data,
-				size_t len, loff_t *ppos)
-{
-	if (len) {
-		if (!nowayout) {
-			size_t i;
-
-			/* In case it was set long ago */
-			expect_close = 0;
-
-			for (i = 0; i != len; i++) {
-				char c;
-				if (get_user(c, data + i))
-					return -EFAULT;
-				if (c == 'V')
-					expect_close = 42;
-			}
-		}
-		bcm63xx_wdt_hw_start();
-	}
-	return len;
-}
-
-static struct watchdog_info bcm63xx_wdt_info = {
-	.identity       = PFX,
-	.options        = WDIOF_SETTIMEOUT |
-				WDIOF_KEEPALIVEPING |
-				WDIOF_MAGICCLOSE,
+static struct watchdog_ops bcm63xx_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = bcm63xx_wdt_start,
+	.stop = bcm63xx_wdt_stop,
+	.set_timeout = bcm63xx_wdt_set_timeout,
 };
 
-
-static long bcm63xx_wdt_ioctl(struct file *file, unsigned int cmd,
-				unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-	int new_value, retval = -EINVAL;
-
-	switch (cmd) {
-	case WDIOC_GETSUPPORT:
-		return copy_to_user(argp, &bcm63xx_wdt_info,
-			sizeof(bcm63xx_wdt_info)) ? -EFAULT : 0;
-
-	case WDIOC_GETSTATUS:
-	case WDIOC_GETBOOTSTATUS:
-		return put_user(0, p);
-
-	case WDIOC_SETOPTIONS:
-		if (get_user(new_value, p))
-			return -EFAULT;
-
-		if (new_value & WDIOS_DISABLECARD) {
-			bcm63xx_wdt_hw_stop();
-			retval = 0;
-		}
-		if (new_value & WDIOS_ENABLECARD) {
-			bcm63xx_wdt_hw_start();
-			retval = 0;
-		}
-
-		return retval;
-
-	case WDIOC_KEEPALIVE:
-		bcm63xx_wdt_hw_start();
-		return 0;
-
-	case WDIOC_SETTIMEOUT:
-		if (get_user(new_value, p))
-			return -EFAULT;
-
-		if (bcm63xx_wdt_settimeout(new_value))
-			return -EINVAL;
-
-		bcm63xx_wdt_hw_start();
-
-	case WDIOC_GETTIMEOUT:
-		return put_user(wdt_time, p);
-
-	default:
-		return -ENOTTY;
-
-	}
-}
-
-static const struct file_operations bcm63xx_wdt_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.write		= bcm63xx_wdt_write,
-	.unlocked_ioctl	= bcm63xx_wdt_ioctl,
-	.open		= bcm63xx_wdt_open,
-	.release	= bcm63xx_wdt_release,
-};
-
-static struct miscdevice bcm63xx_wdt_miscdev = {
-	.minor	= WATCHDOG_MINOR,
-	.name	= "watchdog",
-	.fops	= &bcm63xx_wdt_fops,
+static const struct watchdog_info bcm63xx_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.identity = "BCM63xx Watchdog",
 };
 
-
 static int bcm63xx_wdt_probe(struct platform_device *pdev)
 {
-	int ret;
+	struct bcm63xx_wdt_hw *hw;
+	struct watchdog_device *wdd;
 	struct resource *r;
+	int ret;
+
+	hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
+	if (!hw)
+		return -ENOMEM;
+
+	wdd = &hw->wdd;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
@@ -266,58 +156,65 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	bcm63xx_wdt_device.regs = devm_ioremap_nocache(&pdev->dev, r->start,
-							resource_size(r));
-	if (!bcm63xx_wdt_device.regs) {
+	hw->regs = devm_ioremap_nocache(&pdev->dev, r->start, resource_size(r));
+	if (!hw->regs) {
 		dev_err(&pdev->dev, "failed to remap I/O resources\n");
 		return -ENXIO;
 	}
 
-	raw_spin_lock_init(&bcm63xx_wdt_device.lock);
-	bcm63xx_wdt_device.running = false;
+	raw_spin_lock_init(&hw->lock);
+	hw->running = false;
 
-	ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, NULL);
+	wdd->parent = &pdev->dev;
+	wdd->ops = &bcm63xx_wdt_ops;
+	wdd->info = &bcm63xx_wdt_info;
+	wdd->min_timeout = 1;
+	wdd->max_timeout = 0xffffffff / WDT_HZ;
+	wdd->timeout = min(30U, wdd->max_timeout);
+
+	platform_set_drvdata(pdev, hw);
+
+	watchdog_init_timeout(wdd, 0, &pdev->dev);
+	watchdog_set_nowayout(wdd, nowayout);
+
+	ret = watchdog_register_device(wdd);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to register wdt timer isr\n");
+		dev_err(&pdev->dev, "failed to register watchdog device\n");
 		return ret;
 	}
 
-	if (bcm63xx_wdt_settimeout(wdt_time)) {
-		bcm63xx_wdt_settimeout(WDT_DEFAULT_TIME);
-		dev_info(&pdev->dev,
-			": wdt_time value must be 1 <= wdt_time <= %d, using %d\n",
-			WDT_MAX_TIME, wdt_time);
-	}
-
-	ret = misc_register(&bcm63xx_wdt_miscdev);
+	ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, hw);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to register watchdog device\n");
-		goto unregister_timer;
+		dev_err(&pdev->dev, "failed to register wdt timer isr\n");
+		goto unregister_watchdog;
 	}
 
-	dev_info(&pdev->dev, " started, timer margin: %d sec\n",
-						WDT_DEFAULT_TIME);
+	dev_info(&pdev->dev,
+		"%s at MMIO 0x%p (timeout = %us, max_timeout = %us)",
+		dev_name(wdd->dev), hw->regs,
+		wdd->timeout, wdd->max_timeout);
 
 	return 0;
 
-unregister_timer:
-	bcm63xx_timer_unregister(TIMER_WDT_ID);
+unregister_watchdog:
+	watchdog_unregister_device(wdd);
 	return ret;
 }
 
 static int bcm63xx_wdt_remove(struct platform_device *pdev)
 {
-	if (!nowayout)
-		bcm63xx_wdt_hw_stop();
+	struct bcm63xx_wdt_hw *hw = platform_get_drvdata(pdev);
 
-	misc_deregister(&bcm63xx_wdt_miscdev);
 	bcm63xx_timer_unregister(TIMER_WDT_ID);
+	watchdog_unregister_device(&hw->wdd);
 	return 0;
 }
 
 static void bcm63xx_wdt_shutdown(struct platform_device *pdev)
 {
-	bcm63xx_wdt_hw_stop();
+	struct bcm63xx_wdt_hw *hw = platform_get_drvdata(pdev);
+
+	bcm63xx_wdt_stop(&hw->wdd);
 }
 
 static struct platform_driver bcm63xx_wdt_driver = {
-- 
2.1.4

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

  parent reply	other threads:[~2015-11-25 22:40 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-21 19:02 [PATCH 1/4] clocksource: Add brcm,bcm6345-timer device tree binding Simon Arlott
2015-11-21 19:02 ` Simon Arlott
2015-11-21 19:03 ` [PATCH 2/4] MIPS: bmips: Add bcm6345-l2-timer interrupt controller Simon Arlott
2015-11-21 19:04 ` [PATCH 3/4] watchdog: Add brcm,bcm6345-wdt device tree binding Simon Arlott
2015-11-22 22:13   ` Rob Herring
2015-11-22 22:13     ` Rob Herring
2015-11-21 19:05 ` [PATCH 4/4] MIPS: bmips: Convert bcm63xx_wdt to use WATCHDOG_CORE Simon Arlott
2015-11-21 19:05   ` Simon Arlott
2015-11-21 21:32   ` Guenter Roeck
2015-11-21 21:44     ` Simon Arlott
2015-11-21 21:44       ` Simon Arlott
2015-11-22  2:32       ` Guenter Roeck
2015-11-22 14:02         ` [PATCH 4/10] (Was: [PATCH 4/4]) " Simon Arlott
2015-11-22 14:05           ` [PATCH 4/10] watchdog: bcm63xx_wdt: Handle hardware interrupt and remove software timer Simon Arlott
2015-11-24 18:21             ` Guenter Roeck
2015-11-24 18:21               ` Guenter Roeck
2015-11-24 18:21               ` Guenter Roeck
2015-11-25 20:14               ` Jonas Gorski
2015-11-25 20:14                 ` Jonas Gorski
2015-11-25 20:28                 ` Simon Arlott
2015-11-25 20:28                   ` Simon Arlott
2015-11-25 22:33             ` [PATCH (v2) " Simon Arlott
2015-11-25 22:33               ` Simon Arlott
2015-11-22 14:06           ` [PATCH 5/10] watchdog: bcm63xx_wdt: Use WATCHDOG_CORE Simon Arlott
2015-11-22 14:06             ` Simon Arlott
2015-11-25  2:44             ` Guenter Roeck
2015-11-25  2:44               ` Guenter Roeck
2015-11-25 13:02               ` Simon Arlott
2015-11-25 14:10                 ` Guenter Roeck
2015-11-25 14:10                   ` Guenter Roeck
2015-11-25 19:43                   ` Simon Arlott
2015-11-25 19:43                     ` Simon Arlott
2015-11-25 22:40               ` Simon Arlott [this message]
2015-11-25 22:40                 ` [PATCH (v3) 5/11] " Simon Arlott
2015-11-22 14:07           ` [PATCH 6/10] watchdog: bcm63xx_wdt: Obtain watchdog clock HZ from "periph" clk Simon Arlott
2015-11-22 14:07             ` Simon Arlott
2015-11-23 15:02             ` Jonas Gorski
2015-11-23 15:02               ` Jonas Gorski
2015-11-23 18:19               ` Florian Fainelli
2015-11-23 18:19                 ` Florian Fainelli
2015-11-23 19:00                 ` Simon Arlott
2015-11-23 19:00                   ` Simon Arlott
2015-11-24 22:12             ` [PATCH (v2) " Simon Arlott
2015-11-24 22:42               ` Florian Fainelli
2015-11-24 22:42                 ` Florian Fainelli
2015-11-25 22:47                 ` [PATCH (v3) 6/11] " Simon Arlott
2015-11-25 22:47                   ` Simon Arlott
2015-11-22 14:09           ` [PATCH 7/10] watchdog: bcm63xx_wdt: Add get_timeleft function Simon Arlott
2015-11-22 14:09             ` Simon Arlott
2015-11-24 22:15             ` [PATCH (v2) " Simon Arlott
2015-11-24 22:15               ` Simon Arlott
2015-11-24 22:43               ` Florian Fainelli
2015-11-24 22:43                 ` Florian Fainelli
2015-11-25  2:51               ` Guenter Roeck
2015-11-25  2:51                 ` Guenter Roeck
2015-11-25  8:17                 ` Simon Arlott
2015-11-25  8:17                   ` Simon Arlott
2015-11-25 22:50                   ` [PATCH (v3) 7/11] " Simon Arlott
2015-11-25 22:50                     ` Simon Arlott
2015-11-25 22:54                     ` [PATCH (v4) " Simon Arlott
2015-11-25 22:54                       ` Simon Arlott
2015-11-25 22:57                       ` [PATCH (v4) 8/11] watchdog: bcm63xx_wdt: Warn if the watchdog is currently running Simon Arlott
2015-11-25 22:57                         ` Simon Arlott
2015-11-22 14:11           ` [PATCH 8/10] watchdog: bcm63xx_wdt: Remove dependency on mach-bcm63xx functions/defines Simon Arlott
2015-11-22 14:11             ` Simon Arlott
2015-11-22 14:12           ` [PATCH 9/10] watchdog: bcm63xx_wdt: Use bcm63xx_timer interrupt directly Simon Arlott
2015-11-22 14:12             ` Simon Arlott
2015-11-25 23:03             ` [PATCH (v2) 10/11] " Simon Arlott
2015-11-25 23:03               ` Simon Arlott
2015-11-22 14:14           ` [PATCH 10/10] watchdog: bcm63xx_wdt: Use brcm,bcm6345-wdt device tree binding Simon Arlott
2015-11-22 14:14             ` Simon Arlott
2015-11-25 23:09             ` [PATCH (v2) 11/11] " Simon Arlott
2015-11-25 23:09               ` Simon Arlott
2015-11-22 22:12 ` [PATCH 1/4] clocksource: Add brcm,bcm6345-timer " Rob Herring
2015-11-23 15:33 ` Jonas Gorski
2015-11-23 18:55   ` [PATCH (v2) 1/10] " Simon Arlott
2015-11-23 18:55     ` Simon Arlott
2015-11-23 18:57     ` [PATCH (v2) 2/10] MIPS: bmips: Add bcm6345-l2-timer interrupt controller Simon Arlott
2015-11-23 18:57       ` Simon Arlott
2015-11-24 22:10       ` [PATCH (v3) " Simon Arlott
2015-11-24 22:10         ` Simon Arlott
2015-11-24 22:36         ` Florian Fainelli
2015-11-24 22:36           ` Florian Fainelli
2015-11-26 22:32           ` [PATCH (v4) 2/11] " Simon Arlott
2015-11-27  8:37             ` Thomas Gleixner
2015-11-27  8:37               ` Thomas Gleixner
2015-11-28 12:26               ` [PATCH (v5) 3/11] " Simon Arlott
2015-11-28 12:26                 ` Simon Arlott
2015-12-01  0:22                 ` Guenter Roeck
2015-12-01  0:22                   ` Guenter Roeck
2016-05-09 12:01                   ` Álvaro Fernández Rojas
2016-05-09 13:06                     ` Guenter Roeck
2016-05-09 13:06                       ` Guenter Roeck
2016-05-11  6:40                       ` [PATCH 2/4] " Álvaro Fernández Rojas
2015-11-25  3:05     ` [PATCH (v2) 1/10] clocksource: Add brcm,bcm6345-timer device tree binding Rob Herring

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=565638E9.3010304@simon.arlott.org.uk \
    --to=simon@fire.lp0.eu \
    --cc=cernekee@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=f.fainelli@gmail.com \
    --cc=galak@codeaurora.org \
    --cc=ijc+devicetree@hellion.org.uk \
    --cc=jason@lakedaemon.net \
    --cc=jogo@openwrt.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@linux-mips.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=marc.zyngier@arm.com \
    --cc=mark.rutland@arm.com \
    --cc=mbizon@freebox.fr \
    --cc=pawel.moll@arm.com \
    --cc=ralf@linux-mips.org \
    --cc=robh+dt@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=wim@iguana.be \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.