Commit Graph

34 Commits

Author SHA1 Message Date
Brian Norris 8c088370c2 watchdog: dw: save/restore control and timeout across suspend/resume
Some platforms lose this state in suspend. It should be safe to do this
unconditionally.

Signed-off-by: Brian Norris <briannorris@chromium.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2018-03-13 19:14:19 +01:00
Brian Norris a81abbb412 watchdog: dw: RMW the control register
RK3399 has rst_pulse_length in CONTROL_REG[4:2], determining the length
of pulse to issue for system reset. We shouldn't clobber this value,
because that might make the system reset ineffective. On RK3399, we're
seeing that a value of 000b (meaning 2 cycles) yields an unreliable
(partial?) reset, and so we only fully reset after the watchdog fires a
second time. If we retain the system default (010b, or 8 clock cycles),
then the watchdog reset is much more reliable.

Read-modify-write retains the system value and improves reset
reliability.

It seems we were intentionally clobbering the response mode previously,
to ensure we performed a system reset (we don't support an interrupt
notification), so retain that explicitly.

Signed-off-by: Brian Norris <briannorris@chromium.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2018-03-13 19:14:18 +01:00
Oleksij Rempel 1bfe888938 watchdog: dw_wdt: add stop watchdog operation
The only way of stopping the watchdog is by resetting it.
Add the watchdog op for stopping the device and reset if
a reset line is provided.

At same time WDOG_HW_RUNNING should be remove from dw_wdt_start.
As commented by Guenter Roeck:
dw_wdt sets WDOG_HW_RUNNING in its open function. Result is
that the kref_get() in watchdog_open() won't be executed. But then
kref_put() in close will be called since the watchdog now does stop.
This causes the imbalance.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-watchdog@vger.kernel.org
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2017-12-28 20:44:55 +01:00
Steffen Trumtrar 65a3b6935d watchdog: dw_wdt: get reset lines from dt
The dw_wdt has an external reset line, that can keep the device in reset
and therefore rendering it useless and also is the only way of stopping
the watchdog once it was started.

Get the reset lines for this core from the devicetree. As these lines are
optional, use devm_reset_control_get_optional_shared. If the reset line
is not specified in the devicetree, the reset framework will just skip
deasserting and continue.
This way all users of the driver will continue to function without
any harm, even if the reset line is not specified in the devicetree.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Cc: linux-watchdog@vger.kernel.org
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2017-07-03 10:52:04 +02:00
Guenter Roeck a70dcc016f watchdog: dw_wdt: Use watchdog core to install restart handler
Use the infrastructure provided by the watchdog core to install
the restart handler.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2017-02-24 14:00:23 -08:00
Guenter Roeck c97344f73f watchdog: dw_wdt: Read clock rate only once and validate it
Coverity reports:

divide_by_zero: In expression readl(dw_wdt->regs + 8) /
clk_get_rate(dw_wdt->clk), division by expression clk_get_rate(dw_wdt->clk)
which may be zero has undefined behavior.

The clock used for the watchdog timer won't change its rate, so read it
only once during probe. Also validate it and abort the probe function
with an error if it is 0.

Cc: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2016-09-23 08:40:55 +02:00
Guenter Roeck f29a72c24a watchdog: dw_wdt: Convert to use watchdog infrastructure
Convert driver to use watchdog infrastructure. This includes
infrastructure support to handle watchdog keepalive if the watchdog
is running while the watchdog device is closed.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2016-03-16 21:11:21 +01:00
Jisheng Zhang 3024e0d13b watchdog: dw_wdt: fix signedness bug in dw_wdt_top_in_seconds()
On 64bit platforms, "(1 << (16 + top)) / clk_get_rate(dw_wdt.clk)" is
sign-extended to 64bit then converted to unsigned 64bit, finally divide
the clk rate. If the top is the maximum TOP i.e 15, "(1 << (16 +15))"
will be sign-extended to 0xffffffff80000000, then converted to unsigned
0xffffffff80000000, which is a huge number, thus the final result is
wrong.

We fix this issue by giving usigned value(1U in this case) at first.

Let's assume clk rate is 25MHZ,
Before the patch:
dw_wdt_top_in_seconds(15) = -864612050

After the patch:
dw_wdt_top_in_seconds(15) = 85

Signed-off-by: Jisheng Zhang <jszhang@marvell.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2015-12-27 21:04:50 +01:00
Doug Anderson 04b1a62e6b watchdog: dw_wdt: keepalive the watchdog at write time
If you've got code that does this in a tight loop
  1. Open watchdog
  2. Send 'expect close'
  3. Close watchdog
...you'll eventually trigger a watchdog reset.  You can reproduce this
by using daisydog (1) and running:
  while true; do daisydog -c > /dev/null; done

The problem is that each time you write to the watchdog for 'expect
close' it moves the timer .5 seconds out.  The timer thus never fires
and never pats the watchdog for you.

1: http://git.chromium.org/gitweb/?p=chromiumos/third_party/daisydog.git

Signed-off-by: Doug Anderson <dianders@chromium.org>
Tested-by: Jisheng Zhang <jszhang@marvell.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2015-06-22 15:54:31 +02:00
Doug Anderson 7fb466a7a7 watchdog: dw_wdt: No need for a spinlock
Right now the dw_wdt uses a spinlock to protect dw_wdt_open().  The
problem is that while holding the spinlock we call:
-> dw_wdt_set_top()
   -> dw_wdt_top_in_seconds()
      -> clk_get_rate()
         -> clk_prepare_lock()
            -> mutex_lock()

Locking a mutex while holding a spinlock is not allowed and leads to
warnings like "BUG: spinlock wrong CPU on CPU#1", among other
problems.

There's no reason to use a spinlock.  Only dw_wdt_open() was protected
and the test_and_set_bit() at the start of that function protects us
anyway.

Signed-off-by: Doug Anderson <dianders@chromium.org>
Tested-by: Jisheng Zhang <jszhang@marvell.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2015-06-22 15:54:31 +02:00
Doug Anderson b5ade9bc8d watchdog: dw_wdt: Try to get a 30 second watchdog by default
The dw_wdt_set_top() function takes in a value in seconds.  In
dw_wdt_open() we were calling it with a value that's supposed to
represent the maximum value programmed into the "top" register with a
comment saying that we were trying to set the watchdog to its maximum
value.  Instead we ended up setting the watchdog to ~15 seconds.

Let's fix this.  However, setting things to the "max" gives me an 86
second watchdog in the system I'm looking at.  86 seconds feels a
little too long.  We'll explicitly choose 30 seconds as a more
reasonable value.

NOTE: Ideally this driver should be transitioned to be a real watchdog
driver.  Then we could use "watchdog_init_timeout" and let the timeout
be specified in a number of ways (device tree, module parameter, etc).
This patch should be considered a bit of a stopgap solution.

Signed-off-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2015-02-17 21:33:49 +01:00
Doug Anderson a00850107e watchdog: dw_wdt: pat the watchdog before enabling it
On some dw_wdt implementations the "top" register may be initted to 0
at bootup.  In such a case, each "pat" of the watchdog will reset the
timer to 0xffff.  That's pretty short.

The input clock of the wdt can be any of a wide range of values.  On
an rk3288 system, I've seen the wdt clock be 24.75 MHz.  That means
each tick is ~40ns and we'll count to 0xffff in ~2.6ms.

Because of the above two facts, it's a really good idea to pat the
watchdog after initting the "top" register properly and before
enabling the watchdog.  If you don't then there's no way we'll get the
next heartbeat in time.

Jisheng Zhang fixed this problem on some dw_wdt versions by using the
TOP_INIT feature.  However, the dw_wdt on rk3288 doesn't have TOP_INIT
so it's a good idea to also pat the watchdog manually.

Signed-off-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2015-02-17 21:33:43 +01:00
Greg Kroah-Hartman a8a93c6f99 Merge branch 'platform/remove_owner' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux into driver-core-next
Remove all .owner fields from platform drivers
2014-11-03 19:53:56 -08:00
Jisheng Zhang 31228f43ab watchdog: dw_wdt: add restart handler support
The kernel core now provides an API to trigger a system restart.
Register with it to support restarting the system via. watchdog.

Signed-off-by: Jisheng Zhang <jszhang@marvell.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2014-10-20 21:03:06 +02:00
Jisheng Zhang dfa07141e7 watchdog: dw_wdt: initialise TOP_INIT in dw_wdt_set_top()
The TOP_INIT, ie bit 4-7 of the WDOG_TIMEOUT_RANGE_REG_OFFSET register
may be zero, so the timeout period may be very short after initialization
is done, thus the system may be reset soon after enabling. We fix this
problem by also initialising the TOP_INIT when setting TOP in function
dw_wdt_set_top().

Signed-off-by: Jisheng Zhang <jszhang@marvell.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2014-10-20 20:50:28 +02:00
Wolfram Sang fa21a580de watchdog: drop owner assignment from platform_drivers
A platform_driver does not need to set an owner, it will be populated by the
driver core.

Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
2014-10-20 16:21:56 +02:00
George Cherian 4bba08dda4 watchdog: dw_wdt: Remove the un-necessary check after platform_get_resource()
devm_ioremap_resource() checks for valid resource.
Remove the un-necessary check after platform_get_resource().

Signed-off-by: George Cherian <george.cherian@ti.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2014-08-05 22:42:18 +02:00
Baruch Siach 58a251f2c2 watchdog: dw_wdt: remove build dependencies
There is nothing ARM specific in this driver, and we intend to use it on the
Xtensa architecture. Also, clk.h now includes stubs for !CONFIG_HAVE_CLK, so
the driver should build anyway.

Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Acked-by: Jamie Iles <jamie@jamieiles.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2014-01-28 21:25:46 +01:00
Dinh Nguyen 58e5637333 watchdog: dw: Enable OF support for DW watchdog timer
Add device tree support to the DW watchdog timer.

Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
Acked-by: Jamie Iles <jamie@jamieiles.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Pavel Machek <pavel@denx.de>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Cc: Viresh Kumar <viresh.linux@gmail.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: devicetree@vger.kernel.org
Cc: linux-watchdog@vger.kernel.org
2013-11-17 19:38:26 +01:00
Jean Delvare 487722cf2d watchdog: Get rid of MODULE_ALIAS_MISCDEV statements
I just can't find any value in MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR)
and MODULE_ALIAS_MISCDEV(TEMP_MINOR) statements.

Either the device is enumerated and the driver already has a module
alias (e.g. PCI, USB etc.) that will get the right driver loaded
automatically.

Or the device is not enumerated and loading its driver will lead to
more or less intrusive hardware poking. Such hardware poking should be
limited to a bare minimum, so the user should really decide which
drivers should be tried and in what order. Trying them all in
arbitrary order can't do any good.

On top of that, loading that many drivers at once bloats the kernel
log. Also many drivers will stay loaded afterward, bloating the output
of "lsmod" and wasting memory. Some modules (cs5535_mfgpt which gets
loaded as a dependency) can't even be unloaded!

If defining char-major-10-130 is needed then it should happen in
user-space.

Signed-off-by: Jean Delvare <jdelvare@suse.de>
Acked-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Mike Frysinger <vapier.adi@gmail.com>
Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Zwane Mwaikambo <zwane@arm.linux.org.uk>
Cc: Jim Cromie <jim.cromie@gmail.com>
2013-11-17 19:38:13 +01:00
Jingoo Han 60295507f6 watchdog: dw_wdt: Add __user annotation
Added __user annotation to fix the following sparse warnings.

drivers/watchdog/dw_wdt.c:206:38: warning: incorrect type in argument 1 (different address spaces)
drivers/watchdog/dw_wdt.c:206:38:    expected void [noderef] <asn:1>*to
drivers/watchdog/dw_wdt.c:206:38:    got struct watchdog_info *<noident>
drivers/watchdog/dw_wdt.c:211:24: warning: incorrect type in initializer (different address spaces)
drivers/watchdog/dw_wdt.c:211:24:    expected int const [noderef] <asn:1>*register __p
drivers/watchdog/dw_wdt.c:211:24:    got int *<noident>

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Acked-by: Jamie Iles <jamie@jamieiles.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2013-11-17 19:34:32 +01:00
Heiko Stübner 280103e6b5 watchdog: dw_wdt: use clk_prepare_enable and clk_disable_unprepare
This is necessary to make the driver work with platforms using the
common clock framework.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2013-11-17 19:33:56 +01:00
Heiko Stübner ad83c6cbf3 watchdog: dw_wdt: convert to SIMPLE_DEV_PM_OPS
The dw_wdt only provides PM_SLEEP operations, so convert the driver
to use SIMPLE_DEV_PM_OPS instead of populating the struct manually.
This has the added effect of simplifying the CONFIG_PM ifdefs.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2013-11-17 19:30:06 +01:00
Sachin Kamat 0b93026199 watchdog: dw_wdt: Staticize local symbol
'dw_wdt_write' is used only in this file. Make it static.

Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2013-07-11 21:00:24 +02:00
Jingoo Han cf3cc8c252 watchdog: dw_wdt: use devm_clk_get()
Use devm_clk_get() to make cleanup paths more simple.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2013-07-11 20:59:08 +02:00
Thierry Reding 4c271bb67c watchdog: Convert to devm_ioremap_resource()
Convert all uses of devm_request_and_ioremap() to the newly introduced
devm_ioremap_resource() which provides more consistent error handling.

devm_ioremap_resource() provides its own error messages so all explicit
error messages can be removed from the failure code paths.

Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Cc: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-01-25 12:21:48 -08:00
Bill Pemberton 4b12b896c2 watchdog: remove use of __devexit
CONFIG_HOTPLUG is going away as an option so __devexit is no
longer needed.

Signed-off-by: Bill Pemberton <wfp5p@virginia.edu>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-11-28 12:00:24 -08:00
Bill Pemberton 2d991a164a watchdog: remove use of __devinit
CONFIG_HOTPLUG is going away as an option so __devinit is no longer
needed.

Signed-off-by: Bill Pemberton <wfp5p@virginia.edu>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-11-28 12:00:24 -08:00
Bill Pemberton 82268714bd watchdog: remove use of __devexit_p
CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
needed.

Signed-off-by: Bill Pemberton <wfp5p@virginia.edu>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-11-28 12:00:24 -08:00
Wim Van Sebroeck 86a1e1896c watchdog: nowayout is bool
nowayout is actually a boolean value.
So make it bool for all watchdog device drivers.

Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2012-03-27 20:06:02 +02:00
Joe Perches 27c766aaac watchdog: Use pr_<fmt> and pr_<level>
Use the current logging styles.

Make sure all output has a prefix.
Add missing newlines.
Remove now unnecessary PFX, NAME, and miscellaneous other #defines.
Coalesce formats.

Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2012-03-27 19:59:26 +02:00
Julia Lawall 52ea9a7d79 watchdog: dw_wdt.c: use devm_request_and_ioremap
Reimplement a call to devm_request_mem_region followed by a call to ioremap
or ioremap_nocache by a call to devm_request_and_ioremap.

The semantic patch that makes this transformation is as follows:
(http://coccinelle.lip6.fr/)

// <smpl>
@nm@
expression myname;
identifier i;
@@

struct platform_driver i = { .driver = { .name = myname } };

@@
expression dev,res,size;
expression nm.myname;
@@

-if (!devm_request_mem_region(dev, res->start, size,
-                              \(res->name\|dev_name(dev)\|myname\))) {
-   ...
-   return ...;
-}
... when != res->start
(
-devm_ioremap(dev,res->start,size)
+devm_request_and_ioremap(dev,res)
|
-devm_ioremap_nocache(dev,res->start,size)
+devm_request_and_ioremap(dev,res)
)
... when any
    when != res->start
// </smpl>

Signed-off-by: Julia Lawall <julia@diku.dk>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2012-01-27 09:53:28 +01:00
Axel Lin b8ec61189f watchdog: convert drivers/watchdog/* to use module_platform_driver()
This patch converts the drivers in drivers/watchdog/* to use the
module_platform_driver() macro which makes the code smaller and a bit
simpler.

Signed-off-by: Axel Lin <axel.lin@gmail.com>
Cc: Nicolas Thill <nico@openwrt.org>
Cc: Florian Fainelli <florian@openwrt.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Paul Cercueil <paul@crapouillou.net>
Cc: Marc Zyngier <maz@misterjones.org>
Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: Alejandro Cabrera <aldaya@gmail.com>
Cc: "George G. Davis" <gdavis@mvista.com>
Cc: Sylver Bruneau <sylver.bruneau@googlemail.com>
Cc: Vitaly Wool <vital@embeddedalley.com>
Cc: Mika Westerberg <mika.westerberg@iki.fi>
Cc: Timo Kokkonen <timo.t.kokkonen@nokia.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2012-01-06 15:17:25 +01:00
Jamie Iles c9353ae1c6 watchdog: add support for the Synopsys DesignWare WDT
The Synopsys DesignWare watchdog is found in several ARM based systems
and provides a choice of 16 timeout periods depending on the clock
input.  The watchdog cannot be disabled once started.

Signed-off-by: Jamie Iles <jamie@jamieiles.com>
Acked-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
2011-07-22 08:57:38 +00:00