// SPDX-License-Identifier: GPL-2.0+ /* * drivers/char/watchdog/sp805-wdt.c * * Watchdog driver for ARM SP805 watchdog module * * Copyright (C) 2010 ST Microelectronics * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2 or later. This program is licensed "as is" without any * warranty of any kind, whether express or implied.
*/
/* This routine finds load value that will reset system in required timeout */ staticint wdt_setload(struct watchdog_device *wdd, unsignedint timeout)
{ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
u64 load, rate;
rate = wdt->rate;
/* * sp805 runs counter with given value twice, after the end of first * counter it gives an interrupt and then starts counter again. If * interrupt already occurred then it resets the system. This is why * load is half of what should be required.
*/
load = div_u64(rate, 2) * timeout - 1;
/* returns number of seconds left for reset to occur */ staticunsignedint wdt_timeleft(struct watchdog_device *wdd)
{ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
u64 load;
/*If the interrupt is inactive then time left is WDTValue + WDTLoad. */ if (!(readl_relaxed(wdt->base + WDTRIS) & INT_MASK))
load += (u64)wdt->load_val + 1;
spin_unlock(&wdt->lock);
wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) {
ret = -ENOMEM; goto err;
}
wdt->base = devm_ioremap_resource(&adev->dev, &adev->res); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base);
/* * 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");
/* * If 'timeout-sec' devicetree property is specified, use that. * Otherwise, use DEFAULT_TIMEOUT
*/
wdt->wdd.timeout = DEFAULT_TIMEOUT;
watchdog_init_timeout(&wdt->wdd, 0, &adev->dev);
wdt_setload(&wdt->wdd, wdt->wdd.timeout);
/* * If HW is already running, enable/reset the wdt and set the running * bit to tell the wdt subsystem
*/ if (wdt_is_running(&wdt->wdd)) {
wdt_enable(&wdt->wdd);
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
}
watchdog_stop_on_reboot(&wdt->wdd);
ret = watchdog_register_device(&wdt->wdd); if (ret) goto err;
amba_set_drvdata(adev, wdt);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.