static int fintek_wdt_probe()

in f71808e_wdt.c [445:535]


static int fintek_wdt_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct fintek_wdt_pdata *pdata;
	struct watchdog_device *wdd;
	struct fintek_wdt *wd;
	int wdt_conf, err = 0;
	struct resource *res;
	int sioaddr;

	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
	if (!res)
		return -ENXIO;

	sioaddr = res->start;

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

	pdata = dev->platform_data;

	wd->type = pdata->type;
	wd->sioaddr = sioaddr;
	wd->ident.options = WDIOF_SETTIMEOUT
			| WDIOF_MAGICCLOSE
			| WDIOF_KEEPALIVEPING
			| WDIOF_CARDRESET;

	snprintf(wd->ident.identity,
		sizeof(wd->ident.identity), "%s watchdog",
		fintek_wdt_names[wd->type]);

	err = superio_enter(sioaddr);
	if (err)
		return err;
	superio_select(wd->sioaddr, SIO_F71808FG_LD_WDT);

	wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF);

	/*
	 * We don't want WDTMOUT_STS to stick around till regular reboot.
	 * Write 1 to the bit to clear it to zero.
	 */
	superio_outb(sioaddr, F71808FG_REG_WDT_CONF,
		     wdt_conf | BIT(F71808FG_FLAG_WDTMOUT_STS));

	wdd = &wd->wdd;

	if (fintek_wdt_is_running(wd, wdt_conf))
		set_bit(WDOG_HW_RUNNING, &wdd->status);

	superio_exit(sioaddr);

	wdd->parent		= dev;
	wdd->info               = &wd->ident;
	wdd->ops                = &fintek_wdt_ops;
	wdd->min_timeout        = 1;
	wdd->max_timeout        = WATCHDOG_MAX_TIMEOUT;

	watchdog_set_drvdata(wdd, wd);
	watchdog_set_nowayout(wdd, nowayout);
	watchdog_stop_on_unregister(wdd);
	watchdog_stop_on_reboot(wdd);
	watchdog_init_timeout(wdd, start_withtimeout ?: timeout, NULL);

	if (wdt_conf & BIT(F71808FG_FLAG_WDTMOUT_STS))
		wdd->bootstatus = WDIOF_CARDRESET;

	/*
	 * WATCHDOG_HANDLE_BOOT_ENABLED can result in keepalive being directly
	 * called without a set_timeout before, so it needs to be done here
	 * unconditionally.
	 */
	fintek_wdt_set_timeout(wdd, wdd->timeout);
	fintek_wdt_set_pulse_width(wd, pulse_width);

	if (start_withtimeout) {
		err = fintek_wdt_start(wdd);
		if (err) {
			dev_err(dev, "cannot start watchdog timer\n");
			return err;
		}

		set_bit(WDOG_HW_RUNNING, &wdd->status);
		dev_info(dev, "watchdog started with initial timeout of %u sec\n",
			 start_withtimeout);
	}

	return devm_watchdog_register_device(dev, wdd);
}