微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > S3C2440驱动篇—看门狗驱动分析

S3C2440驱动篇—看门狗驱动分析

时间:11-19 来源:互联网 点击:
Linux-2.6.32.2内核自带S3C2440看门狗驱动,只需要配置一下就可以使用。驱动源代码位于drivers/watchdog/s3c2410_wdt.c,由于驱动使用了平台设备,有关平台设备学习参考上一篇文章。

驱动实现:

#include #include #include #include #include #include #include #include #include #include interrupt.h>#include #include #include #include #undef S3C_VA_WATCHDOG#define S3C_VA_WATCHDOG (0)#include #define PFX "s3c2410-wdt: "#define CONFIG_S3C2410_WATCHDOG_ATBOOT		(0)#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME	(15)static int nowayout	= WATCHDOG_NOWAYOUT;static int tmr_margin	= CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;static int tmr_atboot	= CONFIG_S3C2410_WATCHDOG_ATBOOT;static int soft_noboot;static int debug;module_param(tmr_margin,  int, 0);module_param(tmr_atboot,  int, 0);module_param(nowayout,    int, 0);module_param(soft_noboot, int, 0);module_param(debug,	  int, 0);static unsigned long open_lock;static struct device    *wdt_dev;	/* platform device attached to */static struct resource	*wdt_mem;static struct resource	*wdt_irq;static struct clk	*wdt_clock;static void __iomem	*wdt_base;static unsigned int	 wdt_count;static char		 expect_close;static DEFINE_SPINLOCK(wdt_lock);/* watchdog control routines */#define DBG(msg...) do { \if (debug) \printk(KERN_INFO msg); \} while (0)/* functions */static void s3c2410wdt_keepalive(void) //喂狗{spin_lock(&wdt_lock);writel(wdt_count, wdt_base + S3C2410_WTCNT);spin_unlock(&wdt_lock);}static void __s3c2410wdt_stop(void){unsigned long wtcon;wtcon = readl(wdt_base + S3C2410_WTCON);wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN);writel(wtcon, wdt_base + S3C2410_WTCON);}static void s3c2410wdt_stop(void)   //停止看门狗{spin_lock(&wdt_lock);__s3c2410wdt_stop();spin_unlock(&wdt_lock);}static void s3c2410wdt_start(void)  //启动看门狗{unsigned long wtcon;spin_lock(&wdt_lock);__s3c2410wdt_stop();wtcon = readl(wdt_base + S3C2410_WTCON);wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_div128;if (soft_noboot) {wtcon |= S3C2410_WTCON_INTEN;wtcon &= ~S3C2410_WTCON_RSTEN;} else {wtcon &= ~S3C2410_WTCON_INTEN;wtcon |= S3C2410_WTCON_RSTEN;}DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n",__func__, wdt_count, wtcon);writel(wdt_count, wdt_base + S3C2410_WTDAT);writel(wdt_count, wdt_base + S3C2410_WTCNT);writel(wtcon, wdt_base + S3C2410_WTCON);spin_unlock(&wdt_lock);}static int s3c2410wdt_set_heartbeat(int timeout)   //根据timeout时间设置看门狗定时器初始值{unsigned int freq = clk_get_rate(wdt_clock);unsigned int count;unsigned int divisor = 1;unsigned long wtcon;if (timeout < 1)return -EINVAL;freq /= 128;count = timeout * freq;DBG("%s: count=%d, timeout=%d, freq=%d\n",__func__, count, timeout, freq);/* if the count is bigger than the watchdog register,then work out what we need to do (and if) we canactually make this value*/if (count >= 0x10000) {for (divisor = 1; divisor <= 0x100; divisor++) {if ((count / divisor) < 0x10000)break;}if ((count / divisor) >= 0x10000) {dev_err(wdt_dev, "timeout %d too big\n", timeout);return -EINVAL;}}tmr_margin = timeout;DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n",__func__, timeout, divisor, count, count/divisor);count /= divisor;wdt_count = count;/* update the pre-scaler */wtcon = readl(wdt_base + S3C2410_WTCON);wtcon &= ~S3C2410_WTCON_PRESCALE_MASK;wtcon |= S3C2410_WTCON_PRESCALE(divisor-1);writel(count, wdt_base + S3C2410_WTDAT);writel(wtcon, wdt_base + S3C2410_WTCON);return 0;}/**	/dev/watchdog handling*/static int s3c2410wdt_open(struct inode *inode, struct file *file){if (test_and_set_bit(0, &open_lock))return -EBUSY;if (nowayout)     /*nowayout是内涵配置选项,如果配置则看门狗不能被关闭*/__module_get(THIS_MODULE);/*如果内核配置了CONFIG_WATCHDOG_NOWAYOUT项,则使模块使用计数加1*/expect_close = 0;/* start the timer */s3c2410wdt_start();return nonseekable_open(inode, file);/*表示返回的这个设备文件是不可以被seek操作的,nonseekable_open定义在fs.h中*/}static int s3c2410wdt_release(struct inode *inode, struct file *file){/**	Shut off the timer.* 	Lock it in if its a module and we set nowayout*/if (expect_close == 42)s3c2410wdt_stop();else {dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");s3c2410wdt_keepalive();}expect_close = 0;clear_bit(0, &open_lock);return 0;}static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,size_t len, loff_t *ppos){/**	Refresh the timer.*/if (len) {if (!nowayout) { /*如果没有配置内核CONFIG_WATCHDOG_NOWAYOUT选项,WATCHDOG_NOWAYOUT宏位于include/linux/watchdog.h*/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;}}/*上面的意思是想要看门狗定时器可以被关闭,则内核不要配置CONFIG_WATCHDOG_NOWAYOUT选项,对于下面这里还要“喂狗”一次,我刚开始觉得不需要,因为在看门狗            

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top