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

本系列文章基于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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值