#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/gfp.h>
#include <linux/of.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fcntl.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <asm/current.h>
static int major=0;
static struct class *sr501_class;
static struct gpio_desc* sr501_gpio=NULL;
static int sr501_flag=0;
#define SR501_MAX 5
static char sr501_buf[SR501_MAX]={0};
static int irq;
static DECLARE_WAIT_QUEUE_HEAD(sr501_wait);
/* 实现对应的open/read/write等函数,填入file_operations结构体 */
static ssize_t sr501_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
int len = (size < 4)? size : 4;
wait_event_interruptible(sr501_wait, sr501_flag);
copy_to_user(buf, &sr501_flag,len);
printk("%s %s line %d,val=%x\n", __FILE__, __FUNCTION__, __LINE__,sr501_flag);
sr501_flag=0;
return len;
}
static unsigned int sr501_drv_poll(struct file *fp, poll_table * wait)
{
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
poll_wait(fp, &sr501_wait, wait);
return 0 ;
}
static struct file_operations sr501_drv = {
.owner = THIS_MODULE,
.read = sr501_drv_read,
.poll = sr501_drv_poll,
};
irqreturn_t sr501_irq(int irq, void *dev_id)
{
int val;
sr501_flag=0x80;
val=gpiod_get_value(sr501_gpio);
sr501_flag|=val;
wake_up(&sr501_wait);
printk("%s line %d,%d\n",__FUNCTION__, __LINE__,sr501_flag);
return IRQ_HANDLED;
}
/* 1. 从platform_device获得GPIO
* 2. gpio=>irq
* 3. request_irq
*/
static int sr501_probe(struct platform_device *pdev)
{
int err;
struct device_node *node = pdev->dev.of_node;
int count;
int i;
//
sr501_gpio=gpiod_get(&pdev->dev,NULL,0);
if(IS_ERR(sr501_gpio))
{
dev_err(&pdev->dev,"Fail to get GPIO for sr501\n");
return PTR_ERR(sr501_gpio);
}
gpiod_direction_input(sr501_gpio);
irq=gpiod_to_irq(sr501_gpio);
request_irq(irq,sr501_irq,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,"sr501_irq",NULL);
/* 注册file_operations */
major = register_chrdev(0, "sr501_chr", &sr501_drv);
sr501_class = class_create(THIS_MODULE, "100ask_sr501_class");
if (IS_ERR(sr501_class)) {
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
unregister_chrdev(major, "100ask_sr501");
gpiod_put(sr501_gpio);
return PTR_ERR(sr501_class);
}
device_create(sr501_class, NULL, MKDEV(major, 0), NULL, "sr501");
printk("%s %s line %d,major:%d\n", __FILE__, __FUNCTION__, __LINE__,major);
return 0;
}
static int sr501_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
int i;
device_destroy(sr501_class, MKDEV(major, 0));
class_destroy(sr501_class);
unregister_chrdev(major, "sr501_chr");
free_irq(irq,&(pdev->dev));
gpiod_put(sr501_gpio);
return 0;
}
static const struct of_device_id ask100_sr501[] = {
{.compatible = "100ask,sr501" },
{ },
};
/* 1. 定义platform_driver */
static struct platform_driver sr501_driver = {
.probe = sr501_probe,
.remove = sr501_remove,
.driver = {
.name = "100ask,sr501",
.of_match_table = ask100_sr501,
},
};
/* 2. 在入口函数注册platform_driver */
static int __init sr501_init(void)
{
int err;
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
err = platform_driver_register(&sr501_driver);
return err;
}
/* 3. 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数
* 卸载platform_driver
*/
static void __exit sr501_exit(void)
{
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
platform_driver_unregister(&sr501_driver);
}
/* 7. 其他完善:提供设备信息,自动创建设备节点 */
module_init(sr501_init);
module_exit(sr501_exit);
MODULE_LICENSE("GPL");
评论0