static int mpc8xxx_wdt_probe()

in mpc8xxx_wdt.c [127:213]


static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
{
	int ret;
	struct resource *res;
	const struct mpc8xxx_wdt_type *wdt_type;
	struct mpc8xxx_wdt_ddata *ddata;
	u32 freq = fsl_get_sys_freq();
	bool enabled;
	struct device *dev = &ofdev->dev;

	wdt_type = of_device_get_match_data(dev);
	if (!wdt_type)
		return -EINVAL;

	if (!freq || freq == -1)
		return -EINVAL;

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

	ddata->base = devm_platform_ioremap_resource(ofdev, 0);
	if (IS_ERR(ddata->base))
		return PTR_ERR(ddata->base);

	enabled = in_be32(&ddata->base->swcrr) & SWCRR_SWEN;
	if (!enabled && wdt_type->hw_enabled) {
		dev_info(dev, "could not be enabled in software\n");
		return -ENODEV;
	}

	res = platform_get_resource(ofdev, IORESOURCE_MEM, 1);
	if (res) {
		bool status;
		u32 __iomem *rsr = ioremap(res->start, resource_size(res));

		if (!rsr)
			return -ENOMEM;

		status = in_be32(rsr) & wdt_type->rsr_mask;
		ddata->wdd.bootstatus = status ? WDIOF_CARDRESET : 0;
		 /* clear reset status bits related to watchdog timer */
		out_be32(rsr, wdt_type->rsr_mask);
		iounmap(rsr);

		dev_info(dev, "Last boot was %scaused by watchdog\n",
			 status ? "" : "not ");
	}

	spin_lock_init(&ddata->lock);

	ddata->wdd.info = &mpc8xxx_wdt_info;
	ddata->wdd.ops = &mpc8xxx_wdt_ops;

	ddata->wdd.timeout = WATCHDOG_TIMEOUT;
	watchdog_init_timeout(&ddata->wdd, timeout, dev);

	watchdog_set_nowayout(&ddata->wdd, nowayout);

	ddata->swtc = min(ddata->wdd.timeout * freq / wdt_type->prescaler,
			  0xffffU);

	/*
	 * If the watchdog was previously enabled or we're running on
	 * MPC8xxx, we should ping the wdt from the kernel until the
	 * userspace handles it.
	 */
	if (enabled)
		mpc8xxx_wdt_start(&ddata->wdd);

	ddata->wdd.max_hw_heartbeat_ms = (ddata->swtc * wdt_type->prescaler) /
					 (freq / 1000);
	ddata->wdd.min_timeout = ddata->wdd.max_hw_heartbeat_ms / 1000;
	if (ddata->wdd.timeout < ddata->wdd.min_timeout)
		ddata->wdd.timeout = ddata->wdd.min_timeout;

	ret = devm_watchdog_register_device(dev, &ddata->wdd);
	if (ret)
		return ret;

	dev_info(dev,
		 "WDT driver for MPC8xxx initialized. mode:%s timeout=%d sec\n",
		 reset ? "reset" : "interrupt", ddata->wdd.timeout);

	platform_set_drvdata(ofdev, ddata);
	return 0;
}