watchdog_dev注册过程分析(待续)
2017-06-19 01:53
211 查看
watchdog以platform的方式写的,驱动中的注册和初始化都在platform_driver结构体中的probe函数中
probe先进行一些初始化和寄存器的设置,最后调用watchdog_register_device注册struct watchdog_device
ret = watchdog_register_device(&s3c2410_wdd);
这个函数在watchdog.h中定义,在watchdog_core.c中实现
nt watchdog_register_device(struct watchdog_device *wdd)
{
int ret;
if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
return -EINVAL;
/* Mandatory operations need to be supported */
if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
return -EINVAL;
/*
* Check that we have valid min and max timeout values, if
* not reset them both to 0 (=not used or unknown)
*/
if (wdd->min_timeout > wdd->max_timeout) {
pr_info("Invalid min and max timeout values, resetting to 0!\n");
wdd->min_timeout = 0;
wdd->max_timeout = 0;
}
/*
* Note: now that all watchdog_device data has been verified, we
* will not check this anymore in other functions. If data gets
* corrupted in a later stage then we expect a kernel panic!
*/
/* We only support 1 watchdog device via the /dev/watchdog interface */
ret = watchdog_dev_register(wdd);
if (ret) {
pr_err("error registering /dev/watchdog (err=%d)\n", ret);
return ret;
}
return 0;
}watchdog_register_device中先判断,传入的struct watchdog_device具有info和ops结构体,且ops中有start和stop。然后调用watchdog_dev.c中的watchdog_dev_register。
ret = watchdog_dev_register(wdd);
int watchdog_dev_register(struct watchdog_device *watchdog)
{
int err;
/* Only one device can register for /dev/watchdog */
if (test_and_set_bit(0, &watchdog_dev_busy)) {
pr_err("only one watchdog can use /dev/watchdog\n");
return -EBUSY;
}
wdd = watchdog;
err = misc_register(&watchdog_miscdev);
if (err != 0) {
pr_err("%s: cannot register miscdev on minor=%d (err=%d)\n",
watchdog->info->identity, WATCHDOG_MINOR, err);
goto out;
}
return 0;
out:
wdd = NULL;
clear_bit(0, &watchdog_dev_busy);
return err;
}
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; wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (wdt_mem == NULL) { dev_err(dev, "no memory resource specified\n"); return -ENOENT; } 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; } /* get the memory region for the watchdog timer */ size = resource_size(wdt_mem); if (!request_mem_region(wdt_mem->start, size, pdev->name)) { dev_err(dev, "failed to get memory region\n"); ret = -EBUSY; goto err; } 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_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_map; } clk_enable(wdt_clock); ret = s3c2410wdt_cpufreq_register(); if (ret < 0) { pr_err("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(&s3c2410_wdd, tmr_margin)) { started = s3c2410wdt_set_heartbeat(&s3c2410_wdd, 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 = 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_cpufreq; } watchdog_set_nowayout(&s3c2410_wdd, nowayout); ret = watchdog_register_device(&s3c2410_wdd); if (ret) { dev_err(dev, "cannot register watchdog (%d)\n", ret); goto err_irq; } if (tmr_atboot && started == 0) { dev_info(dev, "starting watchdog timer\n"); s3c2410wdt_start(&s3c2410_wdd); } 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(&s3c2410_wdd); } /* 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) ? "en" : "dis", (wtcon & S3C2410_WTCON_INTEN) ? "en" : "dis"); return 0; err_irq: free_irq(wdt_irq->start, pdev); err_cpufreq: s3c2410wdt_cpufreq_deregister(); err_clk: clk_disable(wdt_clock); clk_put(wdt_clock); wdt_clock = NULL; err_map: iounmap(wdt_base); err_req: release_mem_region(wdt_mem->start, size); err: wdt_irq = NULL; wdt_mem = NULL; return ret; }
probe先进行一些初始化和寄存器的设置,最后调用watchdog_register_device注册struct watchdog_device
ret = watchdog_register_device(&s3c2410_wdd);
这个函数在watchdog.h中定义,在watchdog_core.c中实现
nt watchdog_register_device(struct watchdog_device *wdd)
{
int ret;
if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
return -EINVAL;
/* Mandatory operations need to be supported */
if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
return -EINVAL;
/*
* Check that we have valid min and max timeout values, if
* not reset them both to 0 (=not used or unknown)
*/
if (wdd->min_timeout > wdd->max_timeout) {
pr_info("Invalid min and max timeout values, resetting to 0!\n");
wdd->min_timeout = 0;
wdd->max_timeout = 0;
}
/*
* Note: now that all watchdog_device data has been verified, we
* will not check this anymore in other functions. If data gets
* corrupted in a later stage then we expect a kernel panic!
*/
/* We only support 1 watchdog device via the /dev/watchdog interface */
ret = watchdog_dev_register(wdd);
if (ret) {
pr_err("error registering /dev/watchdog (err=%d)\n", ret);
return ret;
}
return 0;
}watchdog_register_device中先判断,传入的struct watchdog_device具有info和ops结构体,且ops中有start和stop。然后调用watchdog_dev.c中的watchdog_dev_register。
ret = watchdog_dev_register(wdd);
int watchdog_dev_register(struct watchdog_device *watchdog)
{
int err;
/* Only one device can register for /dev/watchdog */
if (test_and_set_bit(0, &watchdog_dev_busy)) {
pr_err("only one watchdog can use /dev/watchdog\n");
return -EBUSY;
}
wdd = watchdog;
err = misc_register(&watchdog_miscdev);
if (err != 0) {
pr_err("%s: cannot register miscdev on minor=%d (err=%d)\n",
watchdog->info->identity, WATCHDOG_MINOR, err);
goto out;
}
return 0;
out:
wdd = NULL;
clear_bit(0, &watchdog_dev_busy);
return err;
}
相关文章推荐
- EditPlus v2.12 注册过程分析(转)
- platform_device的注册过程分析
- Android应用程序注册广播接收器(registerReceiver)的过程分析
- Dalvik虚拟机JNI方法的注册过程分析
- Dalvik虚拟机JNI方法的注册过程分析
- flashtools注册算法分析过程
- Dalvik虚拟机JNI方法的注册过程分析
- Android应用程序注册广播接收器(registerReceiver)的过程分析
- 以RTC为例分析linux platform_bus platform_device和platform_driver注册过程
- Dalvik虚拟机JNI方法的注册过程分析
- 我在unpack 中写的一些技术文章集合,这些是对一些软件的注册过程进行分析的(比较简单)
- Android应用程序注册广播接收器(registerReceiver)的过程分析
- Android应用程序注册广播接收器(registerReceiver)的过程分析
- 网卡驱动注册到PCI总线这一过程的分析 [复制链接]
- Android应用程序注册广播接收器(registerReceiver)的过程分析
- joomla用户权限分析-用户注册过程 【转】
- 【转】网卡驱动注册到PCI总线这一过程的分析
- curl源码分析(二)协议注册与使用过程
- android 动态注册JNI函数过程源码分析
- Dalvik虚拟机JNI方法的注册过程分析