in sbsa_gwdt.c [257:356]
static int sbsa_gwdt_probe(struct platform_device *pdev)
{
void __iomem *rf_base, *cf_base;
struct device *dev = &pdev->dev;
struct watchdog_device *wdd;
struct sbsa_gwdt *gwdt;
int ret, irq;
u32 status;
gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
if (!gwdt)
return -ENOMEM;
platform_set_drvdata(pdev, gwdt);
cf_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cf_base))
return PTR_ERR(cf_base);
rf_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(rf_base))
return PTR_ERR(rf_base);
/*
* Get the frequency of system counter from the cp15 interface of ARM
* Generic timer. We don't need to check it, because if it returns "0",
* system would panic in very early stage.
*/
gwdt->clk = arch_timer_get_cntfrq();
gwdt->refresh_base = rf_base;
gwdt->control_base = cf_base;
wdd = &gwdt->wdd;
wdd->parent = dev;
wdd->info = &sbsa_gwdt_info;
wdd->ops = &sbsa_gwdt_ops;
wdd->min_timeout = 1;
wdd->timeout = DEFAULT_TIMEOUT;
watchdog_set_drvdata(wdd, gwdt);
watchdog_set_nowayout(wdd, nowayout);
sbsa_gwdt_get_version(wdd);
if (gwdt->version == 0)
wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000;
else
wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000;
status = readl(cf_base + SBSA_GWDT_WCS);
if (status & SBSA_GWDT_WCS_WS1) {
dev_warn(dev, "System reset by WDT.\n");
wdd->bootstatus |= WDIOF_CARDRESET;
}
if (status & SBSA_GWDT_WCS_EN)
set_bit(WDOG_HW_RUNNING, &wdd->status);
if (action) {
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
action = 0;
dev_warn(dev, "unable to get ws0 interrupt.\n");
} else {
/*
* In case there is a pending ws0 interrupt, just ping
* the watchdog before registering the interrupt routine
*/
writel(0, rf_base + SBSA_GWDT_WRR);
if (devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
pdev->name, gwdt)) {
action = 0;
dev_warn(dev, "unable to request IRQ %d.\n",
irq);
}
}
if (!action)
dev_warn(dev, "falling back to single stage mode.\n");
}
/*
* In the single stage mode, The first signal (WS0) is ignored,
* the timeout is (WOR * 2), so the maximum timeout should be doubled.
*/
if (!action)
wdd->max_hw_heartbeat_ms *= 2;
watchdog_init_timeout(wdd, timeout, dev);
/*
* Update timeout to WOR.
* Because of the explicit watchdog refresh mechanism,
* it's also a ping, if watchdog is enabled.
*/
sbsa_gwdt_set_timeout(wdd, wdd->timeout);
watchdog_stop_on_reboot(wdd);
ret = devm_watchdog_register_device(dev, wdd);
if (ret)
return ret;
dev_info(dev, "Initialized with %ds timeout @ %u Hz, action=%d.%s\n",
wdd->timeout, gwdt->clk, action,
status & SBSA_GWDT_WCS_EN ? " [enabled]" : "");
return 0;
}