158 lines
3.6 KiB
C
158 lines
3.6 KiB
C
//#define DEBUG
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/types.h>
|
|
#include <linux/init.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/of_gpio.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/module.h>
|
|
#include <linux/device.h>
|
|
#include <asm/io.h>
|
|
#include <asm/uaccess.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/timer.h>
|
|
#include <linux/jiffies.h>
|
|
|
|
static struct timer_list mytimer;
|
|
static unsigned int hw_margin = 3;
|
|
static int khadas_input_pin;
|
|
static unsigned int khadas_enble = 1;
|
|
|
|
static void time_pre(struct timer_list *timer)
|
|
{
|
|
static unsigned int flag=0;
|
|
flag = !flag;
|
|
gpio_direction_output(khadas_input_pin, flag);
|
|
|
|
//printk("%s\n", __func__);
|
|
mytimer.expires = jiffies + hw_margin * HZ/1000; // 500ms 运行一次
|
|
if(khadas_enble)
|
|
mod_timer(&mytimer, mytimer.expires);
|
|
}
|
|
|
|
/*
|
|
static void wdt_exit(void)
|
|
{
|
|
if(timer_pending(&mytimer))
|
|
{
|
|
del_timer(&mytimer);
|
|
}
|
|
printk("exit Success \n");
|
|
}*/
|
|
|
|
static ssize_t show_enble(struct class *cls,
|
|
struct class_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "%d\n", khadas_enble);
|
|
}
|
|
|
|
static ssize_t store_enble(struct class *cls, struct class_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
int enable;
|
|
|
|
if (kstrtoint(buf, 0, &enable)){
|
|
printk("khadas_enble error\n");
|
|
return -EINVAL;
|
|
}
|
|
printk("khadas_enble=%d\n",enable);
|
|
khadas_enble = enable;
|
|
if(khadas_enble){
|
|
mytimer.expires = jiffies + hw_margin * HZ/1000; // 500ms 运行一次
|
|
mod_timer(&mytimer, mytimer.expires);
|
|
}
|
|
return count;
|
|
}
|
|
|
|
static ssize_t store_pin_out(struct class *cls, struct class_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
int enable;
|
|
|
|
if (kstrtoint(buf, 0, &enable)){
|
|
printk("khadas_pin_out error\n");
|
|
return -EINVAL;
|
|
}
|
|
printk("khadas_pin_out=%d\n",enable);
|
|
gpio_direction_output(khadas_input_pin, enable);
|
|
return count;
|
|
}
|
|
|
|
static struct class_attribute khadas_attrs[] = {
|
|
__ATTR(enble, 0644, show_enble, store_enble),
|
|
__ATTR(pin_out, 0644, NULL, store_pin_out),
|
|
};
|
|
|
|
static void create_khadas_attrs(void)
|
|
{
|
|
int i;
|
|
struct class *khadas_class;
|
|
printk("%s\n",__func__);
|
|
khadas_class = class_create(THIS_MODULE, "khadas");
|
|
if (IS_ERR(khadas_class)) {
|
|
pr_err("create khadas_class debug class fail\n");
|
|
return;
|
|
}
|
|
for (i = 0; i < ARRAY_SIZE(khadas_attrs); i++) {
|
|
if (class_create_file(khadas_class, &khadas_attrs[i]))
|
|
pr_err("create khadas attribute %s fail\n", khadas_attrs[i].attr.name);
|
|
}
|
|
}
|
|
|
|
static int wdt_probe(struct platform_device *pdev)
|
|
{
|
|
const char *value;
|
|
int ret;
|
|
printk("hw_wdt enter probe\n");
|
|
|
|
ret = of_property_read_u32(pdev->dev.of_node,"hw_margin_ms", &hw_margin);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = of_property_read_string(pdev->dev.of_node,
|
|
"hw-gpios", &value);
|
|
if (ret) {
|
|
printk("no hw-gpios");
|
|
return -1;
|
|
} else {
|
|
khadas_input_pin = of_get_named_gpio_flags
|
|
(pdev->dev.of_node,
|
|
"hw-gpios",
|
|
0, NULL);
|
|
printk("hlm hw-gpios: %d.\n", khadas_input_pin);
|
|
ret = gpio_request(khadas_input_pin, "khadas");
|
|
}
|
|
|
|
timer_setup(&mytimer, time_pre, 0);
|
|
mytimer.expires = jiffies + hw_margin * HZ/1000; //// 5ms 运行一次
|
|
add_timer(&mytimer);
|
|
create_khadas_attrs();
|
|
return 0;
|
|
}
|
|
|
|
static const struct of_device_id hw_khadas_wdt_dt_ids[] = {
|
|
{ .compatible = "linux,wdt-khadas", },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(of, hw_khadas_wdt_dt_ids);
|
|
|
|
static struct platform_driver khadas_wdt_driver = {
|
|
.driver = {
|
|
.name = "hw_khadas_wdt",
|
|
.of_match_table = hw_khadas_wdt_dt_ids,
|
|
},
|
|
.probe = wdt_probe,
|
|
};
|
|
|
|
static int __init wdt_drv_init(void)
|
|
{
|
|
return platform_driver_register(&khadas_wdt_driver);
|
|
}
|
|
arch_initcall(wdt_drv_init);
|
|
|
|
MODULE_LICENSE("GPL");
|