static int xwdt_probe()

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;
}