S3C2440驱动篇—看门狗驱动分析
时间:11-19
来源:互联网
点击:
/plat-s3c24xx/s3c2410-clock.c中*/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);/* 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);elsedev_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_clk;}if (tmr_atboot && started == 0) {dev_info(dev, "starting watchdog timer\n");s3c2410wdt_start();} else if (!tmr_atboot) {/* if were 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_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_resource(wdt_mem);kfree(wdt_mem);return ret;}static int __devexit s3c2410wdt_remove(struct platform_device *dev){release_resource(wdt_mem);kfree(wdt_mem);wdt_mem = NULL;free_irq(wdt_irq->start, dev);wdt_irq = NULL;clk_disable(wdt_clock);clk_put(wdt_clock);wdt_clock = NULL;iounmap(wdt_base);misc_deregister(&s3c2410wdt_miscdev);return 0;}static void s3c2410wdt_shutdown(struct platform_device *dev){s3c2410wdt_stop();}#ifdef CONFIG_PM/*对Watchdog平台设备驱动电源管理的支持。CONFIG_PM这个宏定义在内核中,当配置内核时选上电源管理,则Watchdog平台驱动的设备挂起和恢复功能均有效*/static unsigned long wtcon_save;static unsigned long wtdat_save;static int s3c2410wdt_suspend(struct platform_device *dev, pm_message_t state){/* Save watchdog state, and turn it off. */wtcon_save = readl(wdt_base + S3C2410_WTCON);wtdat_save = readl(wdt_base + S3C2410_WTDAT);/* Note that WTCNT doesnt need to be saved. */s3c2410wdt_stop();return 0;}static int s3c2410wdt_resume(struct platform_device *dev){/* Restore watchdog state. */writel(wtdat_save, wdt_base + S3C2410_WTDAT);writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */writel(wtcon_save, wdt_base + S3C2410_WTCON);printk(KERN_INFO PFX "watchdog %sabled\n",(wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");return 0;}#else#define s3c2410wdt_suspend NULL#define s3c2410wdt_resume NULL#endif /* CONFIG_PM *//*注意:这是使用了一个__devexit_p,还有前面使用了__devinit和__devexit,我们还是先来讲讲这个:在Linux内核中,使用了大量不同的宏来标记具有不同作用的函数和数据结构,这些宏在include/linux/init.h头文件中定义,编译器通过这些宏可以把代码优化放到合适的内存位置,以减少内存占用和提高内核效率。__devinit、__devexit就是这些宏之一,在probe()和remove()函数中应该使用__devinit和__devexit宏。又当remove()函数使用了__devexit宏时,则在驱动结构体中一定要使用__devexit_p宏来引用remove(),所以下面就用__devexit_p来引用rtc_remove*/static struct platform_driver s3c2410wdt_driver = {.probe = s3c2410wdt_probe,.remove = __devexit_p(s3c2410wdt_remove),.shutdown = s3c2410wdt_shutdown,.suspend = s3c2410wdt_suspend,.resume =
S3C2440看门狗驱 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)