summaryrefslogtreecommitdiff
path: root/drivers/watchdog/sp805_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/sp805_wdt.c')
-rw-r--r--drivers/watchdog/sp805_wdt.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 190d26e2e75f..c2125f204a13 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/char/watchdog/sp805-wdt.c
*
@@ -11,7 +12,6 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/resource.h>
#include <linux/amba/bus.h>
@@ -23,8 +23,9 @@
#include <linux/math64.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/of.h>
#include <linux/pm.h>
+#include <linux/property.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
@@ -58,9 +59,9 @@
* @wdd: instance of struct watchdog_device
* @lock: spin lock protecting dev structure and io access
* @base: base address of wdt
- * @clk: clock structure of wdt
+ * @clk: (optional) clock structure of wdt
+ * @rate: (optional) clock rate when provided via properties
* @adev: amba device structure of wdt
- * @status: current status of wdt
* @load_val: load value to be set for current timeout
*/
struct sp805_wdt {
@@ -87,7 +88,7 @@ static bool wdt_is_running(struct watchdog_device *wdd)
return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK;
}
-/* This routine finds load value that will reset system in required timout */
+/* This routine finds load value that will reset system in required timeout */
static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
{
struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
@@ -126,7 +127,7 @@ static unsigned int wdt_timeleft(struct watchdog_device *wdd)
/*If the interrupt is inactive then time left is WDTValue + WDTLoad. */
if (!(readl_relaxed(wdt->base + WDTRIS) & INT_MASK))
- load += wdt->load_val + 1;
+ load += (u64)wdt->load_val + 1;
spin_unlock(&wdt->lock);
return div_u64(load, wdt->rate);
@@ -231,6 +232,8 @@ static int
sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
{
struct sp805_wdt *wdt;
+ struct reset_control *rst;
+ u64 rate = 0;
int ret = 0;
wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL);
@@ -243,27 +246,31 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
if (IS_ERR(wdt->base))
return PTR_ERR(wdt->base);
- if (adev->dev.of_node) {
- wdt->clk = devm_clk_get(&adev->dev, NULL);
- if (IS_ERR(wdt->clk)) {
- dev_err(&adev->dev, "Clock not found\n");
- return PTR_ERR(wdt->clk);
- }
- wdt->rate = clk_get_rate(wdt->clk);
- } else if (has_acpi_companion(&adev->dev)) {
- /*
- * When Driver probe with ACPI device, clock devices
- * are not available, so watchdog rate get from
- * clock-frequency property given in _DSD object.
- */
- device_property_read_u64(&adev->dev, "clock-frequency",
- &wdt->rate);
- if (!wdt->rate) {
- dev_err(&adev->dev, "no clock-frequency property\n");
- return -ENODEV;
- }
+ /*
+ * When driver probe with ACPI device, clock devices
+ * are not available, so watchdog rate get from
+ * clock-frequency property given in _DSD object.
+ */
+ device_property_read_u64(&adev->dev, "clock-frequency", &rate);
+
+ wdt->clk = devm_clk_get_optional(&adev->dev, NULL);
+ if (IS_ERR(wdt->clk))
+ return dev_err_probe(&adev->dev, PTR_ERR(wdt->clk), "Clock not found\n");
+
+ wdt->rate = clk_get_rate(wdt->clk);
+ if (!wdt->rate)
+ wdt->rate = rate;
+ if (!wdt->rate) {
+ dev_err(&adev->dev, "no clock-frequency property\n");
+ return -ENODEV;
}
+ rst = devm_reset_control_get_optional_exclusive(&adev->dev, NULL);
+ if (IS_ERR(rst))
+ return dev_err_probe(&adev->dev, PTR_ERR(rst), "Can not get reset\n");
+
+ reset_control_deassert(rst);
+
wdt->adev = adev;
wdt->wdd.info = &wdt_info;
wdt->wdd.ops = &wdt_ops;
@@ -273,6 +280,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
watchdog_set_nowayout(&wdt->wdd, nowayout);
watchdog_set_drvdata(&wdt->wdd, wdt);
watchdog_set_restart_priority(&wdt->wdd, 128);
+ watchdog_stop_on_unregister(&wdt->wdd);
/*
* If 'timeout-sec' devicetree property is specified, use that.
@@ -291,6 +299,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
}
+ watchdog_stop_on_reboot(&wdt->wdd);
ret = watchdog_register_device(&wdt->wdd);
if (ret)
goto err;
@@ -304,14 +313,12 @@ err:
return ret;
}
-static int sp805_wdt_remove(struct amba_device *adev)
+static void sp805_wdt_remove(struct amba_device *adev)
{
struct sp805_wdt *wdt = amba_get_drvdata(adev);
watchdog_unregister_device(&wdt->wdd);
watchdog_set_drvdata(&wdt->wdd, NULL);
-
- return 0;
}
static int __maybe_unused sp805_wdt_suspend(struct device *dev)
@@ -342,6 +349,10 @@ static const struct amba_id sp805_wdt_ids[] = {
.id = 0x00141805,
.mask = 0x00ffffff,
},
+ {
+ .id = 0x001bb824,
+ .mask = 0x00ffffff,
+ },
{ 0, 0 },
};