static int st_wdog_probe()

in st_lpc_wdt.c [150:240]


static int st_wdog_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct of_device_id *match;
	struct device_node *np = dev->of_node;
	struct st_wdog *st_wdog;
	struct regmap *regmap;
	struct clk *clk;
	void __iomem *base;
	uint32_t mode;
	int ret;

	ret = of_property_read_u32(np, "st,lpc-mode", &mode);
	if (ret) {
		dev_err(dev, "An LPC mode must be provided\n");
		return -EINVAL;
	}

	/* LPC can either run as a Clocksource or in RTC or WDT mode */
	if (mode != ST_LPC_MODE_WDT)
		return -ENODEV;

	st_wdog = devm_kzalloc(dev, sizeof(*st_wdog), GFP_KERNEL);
	if (!st_wdog)
		return -ENOMEM;

	match = of_match_device(st_wdog_match, dev);
	if (!match) {
		dev_err(dev, "Couldn't match device\n");
		return -ENODEV;
	}
	st_wdog->syscfg	= (struct st_wdog_syscfg *)match->data;

	base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(base))
		return PTR_ERR(base);

	regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
	if (IS_ERR(regmap)) {
		dev_err(dev, "No syscfg phandle specified\n");
		return PTR_ERR(regmap);
	}

	clk = devm_clk_get(dev, NULL);
	if (IS_ERR(clk)) {
		dev_err(dev, "Unable to request clock\n");
		return PTR_ERR(clk);
	}

	st_wdog->dev		= dev;
	st_wdog->base		= base;
	st_wdog->clk		= clk;
	st_wdog->regmap		= regmap;
	st_wdog->warm_reset	= of_property_read_bool(np, "st,warm_reset");
	st_wdog->clkrate	= clk_get_rate(st_wdog->clk);

	if (!st_wdog->clkrate) {
		dev_err(dev, "Unable to fetch clock rate\n");
		return -EINVAL;
	}
	st_wdog_dev.max_timeout = 0xFFFFFFFF / st_wdog->clkrate;
	st_wdog_dev.parent = dev;

	ret = clk_prepare_enable(clk);
	if (ret) {
		dev_err(dev, "Unable to enable clock\n");
		return ret;
	}
	ret = devm_add_action_or_reset(dev, st_clk_disable_unprepare, clk);
	if (ret)
		return ret;

	watchdog_set_drvdata(&st_wdog_dev, st_wdog);
	watchdog_set_nowayout(&st_wdog_dev, WATCHDOG_NOWAYOUT);

	/* Init Watchdog timeout with value in DT */
	ret = watchdog_init_timeout(&st_wdog_dev, 0, dev);
	if (ret)
		return ret;

	ret = devm_watchdog_register_device(dev, &st_wdog_dev);
	if (ret)
		return ret;

	st_wdog_setup(st_wdog, true);

	dev_info(dev, "LPC Watchdog driver registered, reset type is %s",
		 st_wdog->warm_reset ? "warm" : "cold");

	return ret;
}