in of_xilinx_wdt.c [162:254]
static int xwdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int rc;
u32 pfreq = 0, enable_once = 0;
struct xwdt_device *xdev;
struct watchdog_device *xilinx_wdt_wdd;
xdev = devm_kzalloc(dev, sizeof(*xdev), GFP_KERNEL);
if (!xdev)
return -ENOMEM;
xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
xilinx_wdt_wdd->info = &xilinx_wdt_ident;
xilinx_wdt_wdd->ops = &xilinx_wdt_ops;
xilinx_wdt_wdd->parent = dev;
xdev->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xdev->base))
return PTR_ERR(xdev->base);
rc = of_property_read_u32(dev->of_node, "xlnx,wdt-interval",
&xdev->wdt_interval);
if (rc)
dev_warn(dev, "Parameter \"xlnx,wdt-interval\" not found\n");
rc = of_property_read_u32(dev->of_node, "xlnx,wdt-enable-once",
&enable_once);
if (rc)
dev_warn(dev,
"Parameter \"xlnx,wdt-enable-once\" not found\n");
watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
xdev->clk = devm_clk_get(dev, NULL);
if (IS_ERR(xdev->clk)) {
if (PTR_ERR(xdev->clk) != -ENOENT)
return PTR_ERR(xdev->clk);
/*
* Clock framework support is optional, continue on
* anyways if we don't find a matching clock.
*/
xdev->clk = NULL;
rc = of_property_read_u32(dev->of_node, "clock-frequency",
&pfreq);
if (rc)
dev_warn(dev,
"The watchdog clock freq cannot be obtained\n");
} else {
pfreq = clk_get_rate(xdev->clk);
rc = clk_prepare_enable(xdev->clk);
if (rc) {
dev_err(dev, "unable to enable clock\n");
return rc;
}
rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare,
xdev->clk);
if (rc)
return rc;
}
/*
* Twice of the 2^wdt_interval / freq because the first wdt overflow is
* ignored (interrupt), reset is only generated at second wdt overflow
*/
if (pfreq && xdev->wdt_interval)
xilinx_wdt_wdd->timeout = 2 * ((1 << xdev->wdt_interval) /
pfreq);
spin_lock_init(&xdev->spinlock);
watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
rc = xwdt_selftest(xdev);
if (rc == XWT_TIMER_FAILED) {
dev_err(dev, "SelfTest routine error\n");
return rc;
}
rc = devm_watchdog_register_device(dev, xilinx_wdt_wdd);
if (rc)
return rc;
clk_disable(xdev->clk);
dev_info(dev, "Xilinx Watchdog Timer with timeout %ds\n",
xilinx_wdt_wdd->timeout);
platform_set_drvdata(pdev, xdev);
return 0;
}