diff options
Diffstat (limited to 'drivers/watchdog/sp805_wdt.c')
| -rw-r--r-- | drivers/watchdog/sp805_wdt.c | 67 |
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 }, }; |
