当前位置:   article > 正文

Amlogic A311D 驱动分析系列(一)-看门狗驱动分析_amlogic sdk

amlogic sdk

本系列文章基于Amlogic A311D SDK中的驱动,将我之前阅读代码的一些收获进行总结,算是学习笔记吧。

1.dts配置

先看dts调用的是看门狗的哪个驱动

  1. wdt: watchdog@0xffd0f0d0 {
  2. compatible = "amlogic, meson-wdt";//匹配驱动
  3. status = "okay";
  4. default_timeout=<10>;//默认超时时间
  5. reset_watchdog_method=<1>; /* 0:sysfs,1:kernel *///看门狗复位行为1为kernel复位
  6. reset_watchdog_time=<2>;//复位时间
  7. shutdown_timeout=<10>;//关键时间
  8. firmware_timeout=<6>;
  9. suspend_timeout=<6>;//挂起时间
  10. reg = <0xffd0f0d0 0x10>;//寄存器基地址
  11. clock-names = "xtal";
  12. clocks = <&xtal>;
  13. };

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

  1. static int aml_wdt_probe(struct platform_device *pdev)
  2. {
  3. //看门狗设备--向系统注册
  4. struct watchdog_device *aml_wdt;
  5. //amlogic 看门狗设备
  6. struct aml_wdt_dev *wdev;
  7. int ret;
  8. //创建aml_wdt 结构体
  9. aml_wdt = devm_kzalloc(&pdev->dev, sizeof(*aml_wdt), GFP_KERNEL);
  10. if (!aml_wdt)
  11. return -ENOMEM;
  12. wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
  13. if (!wdev)
  14. return -ENOMEM;
  15. wdev->dev = &pdev->dev;
  16. mutex_init(&wdev->lock);
  17. //读取dts,初始化wdev
  18. aml_init_pdata(wdev);
  19. aml_wdt->info = &aml_wdt_info;
  20. aml_wdt->ops = &aml_wdt_ops;
  21. aml_wdt->min_timeout = wdev->min_timeout;
  22. aml_wdt->max_timeout = wdev->max_timeout;
  23. aml_wdt->timeout = 0xffffffff;
  24. wdev->timeout = 0xffffffff;
  25. watchdog_set_drvdata(aml_wdt, wdev);
  26. platform_set_drvdata(pdev, aml_wdt);
  27. wdev->is_running = false;
  28. //看门狗复位行为 1为由当前驱动来进行看门狗复位
  29. //默认为1
  30. if (wdev->reset_watchdog_method == 1) {
  31. //创建一个任务用来喂狗
  32. INIT_DELAYED_WORK(&wdev->boot_queue, boot_moniter_work);
  33. mod_delayed_work(system_freezable_wq, &wdev->boot_queue,
  34. round_jiffies(msecs_to_jiffies(wdev->reset_watchdog_time*1000)));
  35. aml_wdt_start(aml_wdt);
  36. dev_info(wdev->dev, "creat work queue for watch dog\n");
  37. }
  38. //向系统注册wdt
  39. ret = watchdog_register_device(aml_wdt);
  40. if (ret)
  41. return ret;
  42. //注册PM通知
  43. wdev->pm_notifier = aml_wdt_pm_notifier;
  44. //注册重启通知
  45. wdev->reboot_notifier = aml_wdt_reboot_notifier;
  46. register_pm_notifier(&wdev->pm_notifier);
  47. register_reboot_notifier(&wdev->reboot_notifier);
  48. dev_info(wdev->dev, "AML Watchdog Timer probed done\n");
  49. #ifdef CONFIG_AMLOGIC_DEBUG_LOCKUP
  50. g_awdt = wdev;
  51. #endif
  52. return 0;
  53. }

2.2 喂狗方式

因为采用的是默认的kernel方式,因此在驱动中直接创建了一个任务,并初始化了相关计数器,通过不断的复位看门狗计数实现喂狗。

  1. //喂狗任务
  2. static void boot_moniter_work(struct work_struct *work)
  3. {
  4. struct aml_wdt_dev *wdev = container_of(work, struct aml_wdt_dev,
  5. boot_queue.work);
  6. //复位看门狗操作
  7. reset_watchdog(wdev);
  8. mod_delayed_work(system_freezable_wq, &wdev->boot_queue,
  9. round_jiffies(msecs_to_jiffies(wdev->reset_watchdog_time*1000)));
  10. }
  11. //启动喂狗
  12. static int aml_wdt_start(struct watchdog_device *wdog)
  13. {
  14. struct aml_wdt_dev *wdev = watchdog_get_drvdata(wdog);
  15. mutex_lock(&wdev->lock);
  16. //第一初始化时wdog->timeout=0xffffffff
  17. //此时配置看梦狗计数器为默认的default_timeout(10*one_second(记时单位1000
  18. //这么写的目的是aml_wdt_start还可以提供给上层重新配置
  19. if (wdog->timeout == 0xffffffff)
  20. set_watchdog_cnt(wdev, wdev->default_timeout *
  21. wdev->one_second);
  22. else
  23. set_watchdog_cnt(wdev, wdog->timeout * wdev->one_second);
  24. enable_watchdog(wdev);
  25. mutex_unlock(&wdev->lock);
  26. #if 0
  27. if (wdev->boot_queue)
  28. cancel_delayed_work(&wdev->boot_queue);
  29. #endif
  30. wdev->is_running = true;
  31. dev_info(wdev->dev, "start watchdog\n");
  32. return 0;
  33. }

3.总结

amlogic的看门狗驱动采用了比较简单的方式,就是开启一个任务,然后不断的复位寄存器即可。

看门狗复位寄存器

 看门狗tick

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/713145
推荐阅读
相关标签
  

闽ICP备14008679号