赞
踩
本系列文章基于Amlogic A311D SDK中的驱动,将我之前阅读代码的一些收获进行总结,算是学习笔记吧。
1.dts配置
先看dts调用的是看门狗的哪个驱动
- wdt: watchdog@0xffd0f0d0 {
- compatible = "amlogic, meson-wdt";//匹配驱动
- status = "okay";
- default_timeout=<10>;//默认超时时间
- reset_watchdog_method=<1>; /* 0:sysfs,1:kernel *///看门狗复位行为1为kernel复位
- reset_watchdog_time=<2>;//复位时间
- shutdown_timeout=<10>;//关键时间
- firmware_timeout=<6>;
- suspend_timeout=<6>;//挂起时间
- reg = <0xffd0f0d0 0x10>;//寄存器基地址
- clock-names = "xtal";
- clocks = <&xtal>;
- };
2.驱动分析
代码位置:common\drivers\amlogic\watchdog\meson_wdt.c
meson_wdt注册为platform_driver。
platform_driver驱动编写流程大致如下--
xxx_probe--对应aml_wdt_probe
读取dts获得配置--aml_init_pdata
进行相关操作。
2.1 aml_wdt_probe
- static int aml_wdt_probe(struct platform_device *pdev)
- {
- //看门狗设备--向系统注册
- struct watchdog_device *aml_wdt;
- //amlogic 看门狗设备
- struct aml_wdt_dev *wdev;
- int ret;
-
- //创建aml_wdt 结构体
- aml_wdt = devm_kzalloc(&pdev->dev, sizeof(*aml_wdt), GFP_KERNEL);
- if (!aml_wdt)
- return -ENOMEM;
-
- wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
- if (!wdev)
- return -ENOMEM;
- wdev->dev = &pdev->dev;
- mutex_init(&wdev->lock);
- //读取dts,初始化wdev
- aml_init_pdata(wdev);
-
- aml_wdt->info = &aml_wdt_info;
- aml_wdt->ops = &aml_wdt_ops;
- aml_wdt->min_timeout = wdev->min_timeout;
- aml_wdt->max_timeout = wdev->max_timeout;
- aml_wdt->timeout = 0xffffffff;
- wdev->timeout = 0xffffffff;
-
- watchdog_set_drvdata(aml_wdt, wdev);
- platform_set_drvdata(pdev, aml_wdt);
- wdev->is_running = false;
- //看门狗复位行为 1为由当前驱动来进行看门狗复位
- //默认为1
- if (wdev->reset_watchdog_method == 1) {
- //创建一个任务用来喂狗
- INIT_DELAYED_WORK(&wdev->boot_queue, boot_moniter_work);
- mod_delayed_work(system_freezable_wq, &wdev->boot_queue,
- round_jiffies(msecs_to_jiffies(wdev->reset_watchdog_time*1000)));
- aml_wdt_start(aml_wdt);
- dev_info(wdev->dev, "creat work queue for watch dog\n");
- }
- //向系统注册wdt
- ret = watchdog_register_device(aml_wdt);
- if (ret)
- return ret;
-
- //注册PM通知
- wdev->pm_notifier = aml_wdt_pm_notifier;
- //注册重启通知
- wdev->reboot_notifier = aml_wdt_reboot_notifier;
- register_pm_notifier(&wdev->pm_notifier);
- register_reboot_notifier(&wdev->reboot_notifier);
- dev_info(wdev->dev, "AML Watchdog Timer probed done\n");
- #ifdef CONFIG_AMLOGIC_DEBUG_LOCKUP
- g_awdt = wdev;
- #endif
- return 0;
- }
2.2 喂狗方式
因为采用的是默认的kernel方式,因此在驱动中直接创建了一个任务,并初始化了相关计数器,通过不断的复位看门狗计数实现喂狗。
- //喂狗任务
- static void boot_moniter_work(struct work_struct *work)
- {
- struct aml_wdt_dev *wdev = container_of(work, struct aml_wdt_dev,
- boot_queue.work);
- //复位看门狗操作
- reset_watchdog(wdev);
- mod_delayed_work(system_freezable_wq, &wdev->boot_queue,
- round_jiffies(msecs_to_jiffies(wdev->reset_watchdog_time*1000)));
- }
-
- //启动喂狗
- static int aml_wdt_start(struct watchdog_device *wdog)
- {
- struct aml_wdt_dev *wdev = watchdog_get_drvdata(wdog);
-
- mutex_lock(&wdev->lock);
- //第一初始化时wdog->timeout=0xffffffff
- //此时配置看梦狗计数器为默认的default_timeout(10)*one_second(记时单位1000)
- //这么写的目的是aml_wdt_start还可以提供给上层重新配置
- if (wdog->timeout == 0xffffffff)
- set_watchdog_cnt(wdev, wdev->default_timeout *
- wdev->one_second);
- else
- set_watchdog_cnt(wdev, wdog->timeout * wdev->one_second);
- enable_watchdog(wdev);
- mutex_unlock(&wdev->lock);
- #if 0
- if (wdev->boot_queue)
- cancel_delayed_work(&wdev->boot_queue);
- #endif
- wdev->is_running = true;
- dev_info(wdev->dev, "start watchdog\n");
-
- return 0;
- }
3.总结
amlogic的看门狗驱动采用了比较简单的方式,就是开启一个任务,然后不断的复位寄存器即可。
看门狗复位寄存器
看门狗tick
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。