由于是芯片自带的watchdog,所以一般是有驱动和配置的,我们要做的是打开后验证。
/common/drivers/amlogic/watchdog/gx_wdt.c
1、 dtsi中的配置:
amlogic-watchdog{
compatible = "amlogic, gx-wdt";
status = "okay";
default_timeout=<5>;
reset_watchdog_method=<1>;//0:sysfs,1:kernel
reset_watchdog_time=<2>;
shutdown_timeout=<10>;
firmware_timeout=<6>;
suspend_timeout=<6>;
reg = <0x0 0xc11098d0 0x0 0x10>;
clocks = <&clock CLK_XTAL>;
};
2、 defconfig中打开watchdog的宏:
+CONFIG_WATCHDOG=y
+CONFIG_DW_WATCHDOG=y
3、驱动中添加开关,终止喂狗,和timer API
创建设备节点:
- 创建枚举和结构体
+enum watchdog_Enable_Type {
+ TYPE_DISABLE,
+ TYPE_KERNLE, // auto clean watchdog
+ TYPE_USER //clean watchdog for user
+};
---
struct aml_wdt_dev {
unsigned int min_timeout, max_timeout;
unsigned int default_timeout, reset_watchdog_time, shutdown_timeout;
@@ -46,8 +53,11 @@ struct aml_wdt_dev {
unsigned int reset_watchdog_method;
struct delayed_work boot_queue;
void __iomem *reg_base;
+ int watchdog_enable;
+ int watchdog_timer;
};
- 创建读取feeddog函数
+static ssize_t show_wdt_feeddog(struct class *class,
+ struct class_attribute *attr, char *buf)//添加feeddog读取,共三种状态。
+{
+
+ int ret;
+
+ if (awdtv->watchdog_enable==TYPE_DISABLE)
+ {
+ ret = sprintf(buf, "0 -- disable\n");
+ }
+ else if(awdtv->watchdog_enable==TYPE_KERNLE)
+ {
+ ret = sprintf(buf, "1 -- kernel feed\n");
+ }
+ else{
+ ret = sprintf(buf, "2 -- user feed\n");
+ }
+
+ return ret;
+
+};
+
+
- 创建feeddog写入函数(分别为 关闭、打开、feeddog)
+static ssize_t store_wdt_feeddog(struct class *class,
+ struct class_attribute *attr, const char *buf, size_t count)
+{
+ int type;
+
+ pr_info("jsh-01---\n");
+ sscanf(buf,"%i",&type);
+
+ if(type==0){
+ awdtv->watchdog_enable = TYPE_DISABLE;
+ disable_watchdog(awdtv);
+ pr_info("jsh--type=0---\n");
+ }
+ else if(type==1){
+ awdtv->watchdog_enable = TYPE_KERNLE;
+ enable_watchdog(awdtv);
+ pr_info("jsh--type=1---\n");
+ }else if(type==2){
+// reset_watchdog(awdtv);
+ awdtv->watchdog_enable = TYPE_USER;
+ enable_watchdog(awdtv);
+ pr_info("jsh--type=2---\n");
+ }
+
+
+ return count;
+};
+
- 创建timer读取函数
static ssize_t show_wdt_timer(struct class *class,
+ struct class_attribute *attr, char *buf)
+{
+ //int ret ;
+
+
+ printk("timer : %d\n", jshbuf);
+
+ return sprintf(buf, "%d\n", jshbuf);
+
+
+}
+
+
- 创建timer 写入函数
+static ssize_t store_wdt_timer(struct class *class,
+ struct class_attribute *attr, const char *buf, size_t count)
+{
+
+ int jshtime;
+ pr_info("run jshtime");
+
+ sscanf(buf,"%i",&jshtime);
+ pr_info("jshtime \n");
+
+ awdtv->watchdog_timer = jshtime;
+ set_watchdog_cnt(awdtv, jshtime * awdtv->one_second);
+
+ jshbuf = jshtime;
+ return count;
+}
+
- 创建attribute 添加所创建的节点名称和节点文件目录。
+static struct class_attribute watchdog_class_attrs[] = {
+ __ATTR(wdt_feeddog, S_IRUGO | S_IWUSR , show_wdt_feeddog, store_wdt_feeddog),
+ __ATTR(timer, S_IRUGO | S_IWUSR , show_wdt_timer, store_wdt_timer),
+ __ATTR_NULL
+};
+
+static struct class aml_watchdog_class = {
+ .name = "aml_watchdog",
+ .class_attrs = watchdog_class_attrs,
+};
- probe函数中注册创建的class
static int aml_wdt_probe(struct platform_device *pdev)
{
struct watchdog_device *aml_wdt;
@@ -283,6 +399,7 @@ static int aml_wdt_probe(struct platform_device *pdev)
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);
@@ -300,10 +417,17 @@ static int aml_wdt_probe(struct platform_device *pdev)
if (ret)
return ret;
awdtv = wdev;
+ awdtv->watchdog_enable = TYPE_KERNLE;
register_pm_notifier(&aml_wdt_pm_notifier);
register_reboot_notifier(&aml_wdt_reboot_notifier);
dev_info(wdev->dev, "AML Watchdog Timer probed done\n");
+ ret = class_register(&aml_watchdog_class);
+ if (ret){
+ dev_info(wdev->dev, "jsh-02--probe-class_register-\n");
+ return -1;
+ }
return 0;
}
- remove 中注销该类,以免引起重复注册。
static int aml_wdt_remove(struct platform_device *pdev)
{
struct watchdog_device *wdog = platform_get_drvdata(pdev);
aml_wdt_stop(wdog);
+ class_unregister(&aml_watchdog_class);
return 0;
}