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