static int __init bfin_wdt_init(void) { int ret; stampit(); /* Check that the timeout value is within range */ if (bfin_wdt_set_timeout(timeout)) return -EINVAL; /* Since this is an on-chip device and needs no board-specific * resources, we'll handle all the platform device stuff here. */ ret = platform_driver_register(&bfin_wdt_driver); if (ret) { pr_init(KERN_ERR PFX "unable to register driver\n"); return ret; } bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0); if (IS_ERR(bfin_wdt_device)) { pr_init(KERN_ERR PFX "unable to register device\n"); platform_driver_unregister(&bfin_wdt_driver); return PTR_ERR(bfin_wdt_device); } return 0; }
static void update_timestamp(in_addr_t host) { int i; if (dt_table == NULL) { return; } for (i = 0 ; i < dt_table->size ; ++i) { if (dt_table->entry[i].host == 0) { /* * at the last entry. this host was not found. */ break; } if (dt_table->entry[i].host == host) { dt_table->entry[i].timestamp = stampit(); break; } } return; }
static int __init bfin_wdt_init(void) { int ret; stampit(); /* */ if (bfin_wdt_set_timeout(timeout)) return -EINVAL; /* */ ret = platform_driver_register(&bfin_wdt_driver); if (ret) { pr_err("unable to register driver\n"); return ret; } bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0); if (IS_ERR(bfin_wdt_device)) { pr_err("unable to register device\n"); platform_driver_unregister(&bfin_wdt_driver); return PTR_ERR(bfin_wdt_device); } return 0; }
static ssize_t bfin_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { stampit(); if (len) { if (!nowayout) { size_t i; /* In case it was set long ago */ expect_close = 0; for (i = 0; i != len; i++) { char c; if (get_user(c, data + i)) return -EFAULT; if (c == 'V') expect_close = 42; } } bfin_wdt_keepalive(); } return len; }
static int bfin_wdt_set_timeout(unsigned long t) { u32 cnt; unsigned long flags; stampit(); cnt = t * get_sclk(); if (cnt < get_sclk()) { printk(KERN_WARNING PFX "timeout value is too large\n"); return -EINVAL; } spin_lock_irqsave(&bfin_wdt_spinlock, flags); { int run = bfin_wdt_running(); bfin_wdt_stop(); bfin_write_WDOG_CNT(cnt); if (run) bfin_wdt_start(); } spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); timeout = t; return 0; }
static int bfin_wdt_suspend(struct platform_device *pdev, pm_message_t state) { stampit(); state_before_suspend = bfin_wdt_running(); bfin_wdt_stop(); return 0; }
static int bfin_wdt_resume(struct platform_device *pdev) { stampit(); if (state_before_suspend) { bfin_wdt_set_timeout(timeout); bfin_wdt_start(); } return 0; }
static long bfin_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; stampit(); switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info))) return -EFAULT; else return 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p); case WDIOC_SETOPTIONS: { unsigned long flags; int options, ret = -EINVAL; if (get_user(options, p)) return -EFAULT; spin_lock_irqsave(&bfin_wdt_spinlock, flags); if (options & WDIOS_DISABLECARD) { bfin_wdt_stop(); ret = 0; } if (options & WDIOS_ENABLECARD) { bfin_wdt_start(); ret = 0; } spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); return ret; } case WDIOC_KEEPALIVE: bfin_wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; if (bfin_wdt_set_timeout(new_timeout)) return -EINVAL; } /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } }
/** * bfin_otp_write - write OTP pages * * All writes must be in half page chunks (half page == 64 bits). */ static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos) { ssize_t bytes_done; u32 timing, page, base_flags, flags, ret; u64 content; if (!allow_writes) return -EACCES; if (count % sizeof(u64)) return -EMSGSIZE; if (mutex_lock_interruptible(&bfin_otp_lock)) return -ERESTARTSYS; stampit(); timing = bfin_otp_init_timing(); if (timing == 0) { mutex_unlock(&bfin_otp_lock); return -EIO; } base_flags = OTP_CHECK_FOR_PREV_WRITE; bytes_done = 0; page = *pos / (sizeof(u64) * 2); while (bytes_done < count) { flags = base_flags | (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF); stamp("processing page %i (0x%x:%s) from %p", page, flags, (flags & OTP_UPPER_HALF ? "upper" : "lower"), buff + bytes_done); if (copy_from_user(&content, buff + bytes_done, sizeof(content))) { bytes_done = -EFAULT; break; } ret = bfrom_OtpWrite(page, flags, &content); if (ret & OTP_MASTER_ERROR) { stamp("error from otp: 0x%x", ret); bytes_done = -EIO; break; } if (flags & OTP_UPPER_HALF) ++page; bytes_done += sizeof(content); *pos += sizeof(content); } bfin_otp_deinit_timing(timing); mutex_unlock(&bfin_otp_lock); return bytes_done; }
static int bfin_wdt_release(struct inode *inode, struct file *file) { stampit(); if (expect_close == 42) bfin_wdt_stop(); else { pr_crit("Unexpected close, not stopping watchdog!\n"); bfin_wdt_keepalive(); } expect_close = 0; clear_bit(0, &open_check); return 0; }
static int bfin_wdt_open(struct inode *inode, struct file *file) { stampit(); if (test_and_set_bit(0, &open_check)) return -EBUSY; if (nowayout) __module_get(THIS_MODULE); bfin_wdt_keepalive(); bfin_wdt_start(); return nonseekable_open(inode, file); }
/** * bfin_otp_init - Initialize module * * Registers the device and notifier handler. Actual device * initialization is handled by bfin_otp_open(). */ static int __init bfin_otp_init(void) { int ret; stampit(); ret = misc_register(&bfin_otp_misc_device); if (ret) { pr_init(KERN_ERR PFX "unable to register a misc device\n"); return ret; } pr_init(KERN_INFO PFX "initialized\n"); return 0; }
/** * bfin_otp_write - Write OTP pages * * All writes must be in half page chunks (half page == 64 bits). */ static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos) { stampit(); if (count % sizeof(u64)) return -EMSGSIZE; if (mutex_lock_interruptible(&bfin_otp_lock)) return -ERESTARTSYS; /* need otp_init() documentation before this can be implemented */ mutex_unlock(&bfin_otp_lock); return -EINVAL; }
static long bfin_otp_ioctl(struct file *filp, unsigned cmd, unsigned long arg) { stampit(); switch (cmd) { case OTPLOCK: { u32 timing; int ret = -EIO; if (!allow_writes) return -EACCES; if (mutex_lock_interruptible(&bfin_otp_lock)) return -ERESTARTSYS; timing = bfin_otp_init_timing(); if (timing) { u32 otp_result = bfrom_OtpWrite(arg, OTP_LOCK, NULL); stamp("locking page %lu resulted in 0x%x", arg, otp_result); if (!(otp_result & OTP_MASTER_ERROR)) ret = 0; bfin_otp_deinit_timing(timing); } mutex_unlock(&bfin_otp_lock); return ret; } case MEMLOCK: allow_writes = false; return 0; case MEMUNLOCK: allow_writes = true; return 0; } return -EINVAL; }
/** * bfin_otp_read - Read OTP pages * * All reads must be in half page chunks (half page == 64 bits). */ static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos) { ssize_t bytes_done; u32 page, flags, ret; u64 content; stampit(); if (count % sizeof(u64)) return -EMSGSIZE; if (mutex_lock_interruptible(&bfin_otp_lock)) return -ERESTARTSYS; bytes_done = 0; page = *pos / (sizeof(u64) * 2); while (bytes_done < count) { flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF); stamp("processing page %i (0x%x:%s)", page, flags, (flags & OTP_UPPER_HALF ? "upper" : "lower")); ret = bfrom_OtpRead(page, flags, &content); if (ret & OTP_MASTER_ERROR) { stamp("error from otp: 0x%x", ret); bytes_done = -EIO; break; } if (copy_to_user(buff + bytes_done, &content, sizeof(content))) { bytes_done = -EFAULT; break; } if (flags & OTP_UPPER_HALF) ++page; bytes_done += sizeof(content); *pos += sizeof(content); } mutex_unlock(&bfin_otp_lock); return bytes_done; }
static int bfin_wdt_keepalive(void) { stampit(); bfin_write_WDOG_STAT(0); return 0; }
/** * bfin_otp_exit - Deinitialize module * * Unregisters the device and notifier handler. Actual device * deinitialization is handled by bfin_otp_close(). */ static void __exit bfin_otp_exit(void) { stampit(); misc_deregister(&bfin_otp_misc_device); }
static void bfin_wdt_shutdown(struct platform_device *pdev) { stampit(); bfin_wdt_stop(); }
static int bfin_wdt_stop(void) { stampit(); bfin_write_WDOG_CTL(WDEN_DISABLE); return 0; }
static int bfin_wdt_start(void) { stampit(); bfin_write_WDOG_CTL(WDEN_ENABLE | ICTL_RESET); return 0; }
static int bfin_wdt_running(void) { stampit(); return ((bfin_read_WDOG_CTL() & WDEN_MASK) != WDEN_DISABLE); }