123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/slab.h>
- #include <linux/fs.h>
- #include <linux/cdev.h>
- #include <linux/version.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
- #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");
|