#include #include #include #include #include #include #include #include #include #include "wdog.h" struct cdev *cdev_siswdog; void siswdog_stimeout(int devno, int preferred_timeout) { DebugPrint("[WDOG] setting timeout for wdog[%d] \n", devno); if((devno < 1) || (devno > 2)){ DebugPrint("[WDOG] Error -- There's NO WAY to set wdog[%d] timeout !! \n", devno); return; } if(devno == 1){ #if 0 __u32 temp = readl((__u32 *)WDT1_Ctl_Reg) & 0xe0000000; DebugPrint("[WDOG] setting timeout for wdog[%d] : %d us \n", devno, preferred_timeout); writel((preferred_timeout & 0x1fffffff), (__u32 *)WDT1_Ctl_Reg); writel(temp | (preferred_timeout & 0x1fffffff), (__u32 *)WDT1_Ctl_Reg); #endif } else if(devno == 2){ __u32 temp = readl((__u32 *)WDT2_Ctl_Reg) & 0xe0000000; DebugPrint("[WDOG] setting timeout for wdog[%d] : %d ms \n", devno, preferred_timeout); writel((preferred_timeout & 0x1fffffff), (__u32 *)WDT2_Ctl_Reg); writel(temp | (preferred_timeout & 0x1fffffff), (__u32 *)WDT2_Ctl_Reg); } } void siswdog_keepalive(int devno) { if(devno == 0){ set_bit(WDT0_Refresh_bit, (void *)(WDT0_Ctl_Reg)); } else if(devno == 1){ set_bit(WDT1_Refresh_bit, (void *)(WDT0_Ctl_Reg)); } else if(devno == 2){ set_bit(WDT2_Refresh_bit, (void *)(WDT0_Ctl_Reg)); } } EXPORT_SYMBOL(siswdog_keepalive); #if 1 void siswdog_remove(int devno) { // keep-alive the Watch Dog here for the critical case siswdog_keepalive(devno); if(devno == 0){ set_bit(WDT0_Disable_bit, (void *)(WDT0_Ctl_Reg)); } else if(devno == 1){ clear_bit(WDT1_Eisable_bit, (void *)(WDT1_Ctl_Reg)); } else if(devno == 2){ clear_bit(WDT2_Eisable_bit, (void *)(WDT2_Ctl_Reg)); } else if(devno == 3){ //writel(0, (__u32 *)0xbe0f030c); // clear the Watch Dog 3 } } EXPORT_SYMBOL(siswdog_remove); #endif void siswdog_add(int devno, int preferred_timeout) { siswdog_stimeout(devno, preferred_timeout); // enable the Watch Dog if(devno == 0){ clear_bit(WDT0_Disable_bit, (void *)(WDT0_Ctl_Reg)); } else if(devno == 1){ set_bit(WDT1_Eisable_bit, (void *)(WDT1_Ctl_Reg)); } else if(devno == 2){ set_bit(WDT2_Eisable_bit, (void *)(WDT2_Ctl_Reg)); } #if 0 else if(devno == 3){ writel(SISWDOG3_WarmReset, (__u32 *)WDT3_Ctl_Reg); // set the Watch Dog 3 to "Warm Reset" at once } else if(devno == 4){ writel(SISWDOG3_ColdReset, (__u32 *)WDT3_Ctl_Reg); // set the Watch Dog 3 to "Cold Reset" at once } else if(devno == 5){ writel(SISWDOG3_RTCReset, (__u32 *)WDT3_Ctl_Reg); // set the Watch Dog 3 to "RTC Reset" at once } #endif // keep-alive the Watch Dog here for the critical case siswdog_keepalive(devno); } EXPORT_SYMBOL(siswdog_add); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8) long siswdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) #else ssize_t siswdog_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg) #endif { siswdog_ioctl_data parameter; switch(cmd){ case SISWDOG_ADD: copy_from_user(¶meter, (void *)arg, sizeof(siswdog_ioctl_data)); siswdog_add(parameter.devno, parameter.preferred_timeout); break; #if 1 case SISWDOG_REMOVE: siswdog_remove(arg); break; #endif case SISWDOG_KEEPALIVE: siswdog_keepalive(arg); break; default: break; } return 0; } struct file_operations siswdog_fops = { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8)) .unlocked_ioctl = siswdog_ioctl, #else .ioctl = siswdog_ioctl, #endif .owner = THIS_MODULE, }; int siswdog_init(void){ int ret = 0; int devno = MKDEV(SISWDOG_DEV_MAJOR, 130); cdev_siswdog = cdev_alloc(); cdev_siswdog->owner = THIS_MODULE; cdev_siswdog->ops = &siswdog_fops; ret = cdev_add(cdev_siswdog, devno, 1); if (ret) { printk("\n====[%s, %d], init fail!!! err = %d\n",__FUNCTION__,__LINE__, ret); return -EIO; } *(volatile unsigned int *)(WDT1_Ctl_Reg) = (*(volatile unsigned int *)(WDT1_Ctl_Reg) & ~(0x3 << 29)) | SISWDOG_ColdReset; *(volatile unsigned int *)(WDT2_Ctl_Reg) = (*(volatile unsigned int *)(WDT2_Ctl_Reg) & ~(0x3 << 29)) | SISWDOG_ColdReset; return 0; } #if 0 void siswdog_exit(void){ cdev_del(cdev_siswdog); } #endif #ifndef INIT_BY_KMF module_init(siswdog_init); module_exit(siswdog_exit); #endif MODULE_LICENSE("Dual BSD/GPL");