/* * xwdt_ioctl: * @file: file handle to the device * @cmd: watchdog command * @arg: argument pointer * * The watchdog API defines a common set of functions for all watchdogs * according to their available features. */ static long xwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int status; union { struct watchdog_info __user *ident; int __user *i; } uarg; uarg.i = (int __user *)arg; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETBOOTSTATUS: return put_user(xdev.boot_status, uarg.i); case WDIOC_GETSTATUS: xwdt_get_status(&status); return put_user(status, uarg.i); case WDIOC_KEEPALIVE: xwdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: printk(KERN_INFO "This feature is not implemented yet!\n"); case WDIOC_GETTIMEOUT: if (no_timeout) return -ENOTTY; else return put_user(timeout, uarg.i); default: return -ENOTTY; } }
static int __devinit xwdt_probe(struct platform_device *pdev) { int rc; u32 *tmptr; u32 *pfreq; no_timeout = 0; pfreq = (u32 *)of_get_property(pdev->dev.of_node->parent, "clock-frequency", NULL); if (pfreq == NULL) { pr_warn("The watchdog clock frequency cannot be obtained!\n"); no_timeout = 1; } rc = of_address_to_resource(pdev->dev.of_node, 0, &xdev.res); if (rc) { pr_warn("invalid address!\n"); return rc; } tmptr = (u32 *)of_get_property(pdev->dev.of_node, "xlnx,wdt-interval", NULL); if (tmptr == NULL) { pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n"); no_timeout = 1; } else { xdev.wdt_interval = *tmptr; } tmptr = (u32 *)of_get_property(pdev->dev.of_node, "xlnx,wdt-enable-once", NULL); if (tmptr == NULL) { pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n"); xdev.nowayout = WATCHDOG_NOWAYOUT; } /* * Twice of the 2^wdt_interval / freq because the first wdt overflow is * ignored (interrupt), reset is only generated at second wdt overflow */ if (!no_timeout) timeout = 2 * ((1<<xdev.wdt_interval) / *pfreq); if (!request_mem_region(xdev.res.start, xdev.res.end - xdev.res.start + 1, WATCHDOG_NAME)) { rc = -ENXIO; pr_err("memory request failure!\n"); goto err_out; } xdev.base = ioremap(xdev.res.start, xdev.res.end - xdev.res.start + 1); if (xdev.base == NULL) { rc = -ENOMEM; pr_err("ioremap failure!\n"); goto release_mem; } rc = xwdt_selftest(); if (rc == XWT_TIMER_FAILED) { pr_err("SelfTest routine error!\n"); goto unmap_io; } xwdt_get_status(&xdev.boot_status); rc = misc_register(&xwdt_miscdev); if (rc) { pr_err("cannot register miscdev on minor=%d (err=%d)\n", xwdt_miscdev.minor, rc); goto unmap_io; } if (no_timeout) pr_info("driver loaded (timeout=? sec, nowayout=%d)\n", xdev.nowayout); else pr_info("driver loaded (timeout=%d sec, nowayout=%d)\n", timeout, xdev.nowayout); expect_close = 0; clear_bit(0, &driver_open); return 0; unmap_io: iounmap(xdev.base); release_mem: release_mem_region(xdev.res.start, resource_size(&xdev.res)); err_out: return rc; }