1. 看门狗的框架介绍
看门狗是以misc设备的模式注册到设备中的,没有像其它设备那样复杂
struct miscdevice {
int minor; //此设备号
const char *name; //混杂设备名字
const struct file_operations *fops; //设备的操作函数
struct list_head list; //指向下一个混杂设备
struct device *parent; //指向父设备
struct device *this_device; //指向当前设备结构体
const char *nodename;
mode_t mode;
};
static const struct file_operations s3c2410wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = s3c2410wdt_write,
.unlocked_ioctl = s3c2410wdt_ioctl,
.open = s3c2410wdt_open,
.release = s3c2410wdt_release,
};
static struct miscdevice s3c2410wdt_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &s3c2410wdt_fops,
};2. 看门狗的初始化
直接看s3c2410wdt_probe
static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
{
struct device *dev;
unsigned int wtcon;
int started = 0;
int ret;
int size;
DBG("%s: probe=%p\n", __func__, pdev);
dev = &pdev->dev;
wdt_dev = &pdev->dev;
/* get the memory region for the watchdog timer */
wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (wdt_mem == NULL) {
dev_err(dev, "no memory resource specified\n");
return -ENOENT;
}
size = resource_size(wdt_mem);
if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
dev_err(dev, "failed to get memory region\n");
return -EBUSY;
}
wdt_base = ioremap(wdt_mem->start, size);
if (wdt_base == NULL) {
dev_err(dev, "failed to ioremap() region\n");
ret = -EINVAL;
goto err_req;
}
DBG("probe: mapped wdt_base=%p\n", wdt_base);
wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (wdt_irq == NULL) {
dev_err(dev, "no irq resource specified\n");
ret = -ENOENT;
goto err_map;
}
ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
if (ret != 0) {
dev_err(dev, "failed to install irq (%d)\n", ret);
goto err_map;
}
wdt_clock = clk_get(&pdev->dev, "watchdog");
if (IS_ERR(wdt_clock)) {
dev_err(dev, "failed to find watchdog clock source\n");
ret = PTR_ERR(wdt_clock);
goto err_irq;
}
clk_enable(wdt_clock);
if (s3c2410wdt_cpufreq_register() < 0) {
printk(KERN_ERR PFX "failed to register cpufreq\n");
goto err_clk;
}
/* see if we can actually set the requested timer margin, and if
* not, try the default value */
if (s3c2410wdt_set_heartbeat(tmr_margin)) { //设置看门狗的复位时间
started = s3c2410wdt_set_heartbeat(
CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
if (started == 0)
dev_info(dev,
"tmr_margin value out of range, default %d used\n",
CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
else
dev_info(dev, "default timer value is out of range, "
"cannot start\n");
}
ret = misc_register(&s3c2410wdt_miscdev); //注册混杂设备
if (ret) {
dev_err(dev, "cannot register miscdev on minor=%d (%d)\n",
WATCHDOG_MINOR, ret);
goto err_cpufreq;
}
if (tmr_atboot && started == 0) { //开机时就立即启动看门狗定时器
dev_info(dev, "starting watchdog timer\n");
s3c2410wdt_start();
} else if (!tmr_atboot) {
/* if we're not enabling the watchdog, then ensure it is
* disabled if it has been left running from the bootloader
* or other source */
s3c2410wdt_stop();
}
/* print out a statement of readiness */
wtcon = readl(wdt_base + S3C2410_WTCON);
dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n",
(wtcon & S3C2410_WTCON_ENABLE) ? "" : "in",
(wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis",
(wtcon & S3C2410_WTCON_INTEN) ? "" : "en");
return 0;
err_cpufreq:
s3c2410wdt_cpufreq_deregister();
err_clk:
clk_disable(wdt_clock);
clk_put(wdt_clock);
err_irq:
free_irq(wdt_irq->start, pdev);
err_map:
iounmap(wdt_base);
err_req:
release_mem_region(wdt_mem->start, size);
wdt_mem = NULL;
return ret;
}3. 看门狗的操作函数集
s3c2410wdt_open主要是调用s3c2410wdt_start启动看门狗
s3c2410wdt_release,如果允许关闭,就调用s3c2410wdt_stop关闭看门狗。如果不允许关闭,则调用s3c2410wdt_keepalive,使看门狗成为活动状态。
s3c2410wdt_write,该函数主要用来设置allow_close变量为允许关闭状态。
s3c2410wdt_irq,该中断处理函数的主要功能是喂狗操作,使看门狗重新开始计数。

2157

被折叠的 条评论
为什么被折叠?



