watchdog_dev注册过程分析(待续)

来源:互联网 发布:我爱发明 知乎 编辑:程序博客网 时间:2024/05/19 20:42

watchdog以platform的方式写的,驱动中的注册和初始化都在platform_driver结构体中的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;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);elsedev_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;}



阅读全文
0 0