|
发表于 2019-1-21 16:19:23
只看该作者
沙发
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/leds.h>
#include <linux/io.h>
#include <linux/semaphore.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include<linux/gpio.h>
#include <linux/pinctrl/consumer.h>
#include <asm/delay.h>
#define ENBLK 149
#define DEFAULT_VALUE 255
#define GPIO_IOC_MAGIC 'G'
#define IOCTL_GPIO_SETOUTPUT _IOW(GPIO_IOC_MAGIC, 0, int)
#define IOCTL_GPIO_SETINPUT _IOW(GPIO_IOC_MAGIC, 1, int)
#define IOCTL_GPIO_SETVALUE _IOW(GPIO_IOC_MAGIC, 2, int)
#define IOCTL_GPIO_GETVALUE _IOR(GPIO_IOC_MAGIC, 3, int)
//#define IOCTL_GPIO_BKLTENABLE _IOR(GPIO_IOC_MAGIC, 4, int)
#define GPIO_IOC_MAXNR 3
struct rk_gpio_arg{
int pin;
int data;
};
struct rk_gpio_node{
int pin;
struct rk_gpio_node *next;
};
static int gpio_major = 0;
static int gpio_minor = 0;
static struct class *gpio_class;
static struct device *rk_dev;
static struct cdev gpio_cdev;
static struct rk_gpio_node *head;
static int is_required(int pinnum)
{
struct rk_gpio_node *pnode = head->next;
struct rk_gpio_node *rnode = head;
while(pnode != NULL)
{
if(pnode->pin == pinnum)
return 0;
else
{
rnode = pnode;
pnode = pnode->next;
}
}
printk("New GPIO Registered!\n");
pnode = (struct rk_gpio_node *)kmalloc(sizeof(struct rk_gpio_node), GFP_KERNEL);
if(pnode != NULL)
{
rnode->next = pnode;
pnode->pin = pinnum;
pnode->next = NULL;
}
else
printk("Can't Kmalloc...\n");
return 1;
}
static int gpio_open(struct inode *inode,struct file *filp)
{
return 0;
}
static int gpio_release(struct inode *inode,struct file *filp)
{
return 0;
}
static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int err = 0;
struct rk_gpio_arg *parg = (struct rk_gpio_arg *)arg;
if(is_required(parg->pin))
{
err = gpio_request(parg->pin, "rk_gpio");
if(err != 0)
{
printk("Can't request this gpio!\n");
gpio_free(parg->pin);
}
}
switch (cmd) {
case IOCTL_GPIO_SETOUTPUT:
gpio_direction_output(parg->pin, parg->data);
break;
case IOCTL_GPIO_SETINPUT:
gpio_direction_input(parg->pin);
break;
case IOCTL_GPIO_SETVALUE:
gpio_set_value(parg->pin, parg->data);
break;
case IOCTL_GPIO_GETVALUE:
parg->data = gpio_get_value(parg->pin) ? 1 : 0;
break;
default :
printk(KERN_WARNING "Unsuported Ioctl Cmd\n");
}
return 0;
}
struct file_operations gpio_fops = {
.owner = THIS_MODULE,
.open = gpio_open,
//change by louhn
.unlocked_ioctl = gpio_ioctl,
//.compat_ioctl = gpio_ioctl,
.release = gpio_release,
};
static int __init rk_gpio_init(void)
{
int result;
dev_t dev = 0;
result = alloc_chrdev_region(&dev, gpio_minor, 1,"rk_gpio");
gpio_major = MAJOR(dev);
if (result < 0) {
printk(KERN_WARNING "Can't get major %d\n", gpio_major);
return result;
}
printk(" GPIO Driver Registered.\n");
cdev_init(&gpio_cdev, &gpio_fops);
gpio_cdev.owner = THIS_MODULE;
gpio_cdev.ops = &gpio_fops;
result = cdev_add (&gpio_cdev, dev, 1);
gpio_class = class_create(THIS_MODULE, "rk_gpio");
if (IS_ERR(gpio_class)) {
printk(KERN_WARNING "Class_create faild\n");
cdev_del(&gpio_cdev);
unregister_chrdev_region(dev, 0);
return result;
}
rk_dev = device_create(gpio_class, NULL, dev, 0, "rk_gpio");
head = (struct rk_gpio_node *)kmalloc(sizeof(struct rk_gpio_node), GFP_KERNEL);
if(head == NULL)
{
return -1;
}
else
{
head->pin = 0;
head->next = NULL;
}
return 0;
}
static void __exit rk_gpio_exit(void)
{
dev_t dev = 0;
struct rk_gpio_node *pnode = head->next;
struct rk_gpio_node *rnode = NULL;
while(pnode != NULL )
{
rnode = pnode->next;
kfree(pnode);
pnode = rnode;
}
kfree(head);
dev = MKDEV(gpio_major, gpio_minor);
class_unregister(gpio_class);
class_destroy(gpio_class);
unregister_chrdev_region(dev, 0);
cdev_del(&gpio_cdev);
}
module_init(rk_gpio_init);
module_exit(rk_gpio_exit);
MODULE_DESCRIPTION("Driver for rockchip GPIO");
MODULE_AUTHOR("hzmct.com");
MODULE_LICENSE("GPL");
|
|