通用gpio驱动,可用echo和cat改变电平

现版:echo 0 > /dev/gpio_3_D6
cat /dev/gpio_3_D6

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>		
#include <asm/io.h>
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/delay.h> 
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_address.h>	

struct gpio_kuka_dev
{	
	struct 	cdev 		cdev;
	struct device_node  *nd;
	struct device 		*device;
	dev_t				dev_id;
	int					major;
	unsigned int		gpio;
	int					gpio_enable_value;
};

static struct gpio_kuka_dev *gpio_kuka;
static struct class * gpio_kuka_class;
static int first_read = 1;
static int gpio_kuka_open(struct inode *inode, struct file *pfile) 
{ 
	int ret = 0;
	struct gpio_kuka_dev * dev = container_of(inode->i_cdev, struct gpio_kuka_dev, cdev);
	pfile->private_data = dev;
	
	return ret;
} 

static ssize_t gpio_kuka_read(struct file *pfile, char __user *buf, size_t size, loff_t *offset) 
{ 
	int ret = 0;
	struct gpio_kuka_dev *p;
	char level_str[3] = {0};
	int level = 0;
	p = pfile->private_data;

	level = gpio_get_value(p->gpio);
	sprintf(level_str,"%d\n",level);
	ret = copy_to_user(buf, level_str, sizeof(level_str));
	if(first_read)
	{
		first_read = 0;
		return sizeof(level_str);
	}
	else
	{
		first_read = 1;
		return 0;
	}
} 

static ssize_t gpio_kuka_write(struct file *pfile, const char __user *buf, size_t size, loff_t *offset) 
{ 
	int ret = 0;
	struct gpio_kuka_dev *p;
	char level_str[2] = {0};
	int level = 0;
	
	p = pfile->private_data;
	if(size > 2)
	{
		printk("invalid param\n");
		return -1;
	}
	ret = copy_from_user(&level_str, buf, size);
	level = simple_strtol(level_str, NULL, 10);
	if(level != 0 && level != 1)
	{
		printk("invalid param\n");
		return -1;
	}
	gpio_set_value(p->gpio, level);
	printk("gpio set value %d\n",level);
    return size;
} 

static struct file_operations gpio_kuka_fops = { 
     .owner = THIS_MODULE, 
     .open  = gpio_kuka_open,
     .read  = gpio_kuka_read,
     .write = gpio_kuka_write, 
};   

static struct of_device_id of_gpio_kuka_ids[] = {
   {.compatible = "gpio_kuka"},
   { }   
 };

static int gpio_kuka_probe(struct platform_device *pdev)  
{
	int gpio;
	enum of_gpio_flags flag;

	gpio_kuka = devm_kzalloc(&pdev->dev,sizeof(struct gpio_kuka_dev), GFP_KERNEL);
   	if (!gpio_kuka) {
        return -ENOMEM;
    }

	alloc_chrdev_region(&gpio_kuka->dev_id, 0, 1, pdev->name);
	gpio_kuka->major = MAJOR(gpio_kuka->dev_id);
   	cdev_init(&gpio_kuka->cdev, &gpio_kuka_fops);
	cdev_add(&gpio_kuka->cdev, gpio_kuka->dev_id, 1);
	gpio_kuka_class = class_create(THIS_MODULE, pdev->name);
	gpio_kuka->device = device_create(gpio_kuka_class, NULL, gpio_kuka->dev_id, NULL, pdev->name);

	gpio_kuka->nd =  pdev->dev.of_node;
	gpio = of_get_named_gpio_flags(pdev->dev.of_node, "gpio_kuka", 0, &flag);
	if (!gpio_is_valid(gpio)) {
		printk("kuka-gpio: %d is invalid\n", gpio); return -ENODEV;
    }
	if (gpio_request(gpio, "gpio_kuka")) {
        printk("gpio %d request failed!\n", gpio);
        gpio_free(gpio);
        return -ENODEV;
    }
	gpio_kuka->gpio = gpio;
	gpio_kuka->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
   	gpio_direction_output(gpio_kuka->gpio, gpio_kuka->gpio_enable_value);
    printk("kuka gpio putout\n");
	gpio_kuka->device->gpio = gpio_kuka->gpio;
	
   	return 0; 
} 
  
static int gpio_kuka_remove(struct platform_device *pdev) 
{
	gpio_free(gpio_kuka->gpio);
	cdev_del(&gpio_kuka->cdev);
	unregister_chrdev_region(gpio_kuka->dev_id, 1);
	devm_kfree(&pdev->dev, gpio_kuka);
	return 0; 
} 

static struct platform_driver gpio_driver_kuka = { 
	.driver   = { 
	.owner    = THIS_MODULE, 
	.name     = "gpio_kuka",
	.of_match_table = of_match_ptr(of_gpio_kuka_ids),
	}, 
	.probe 	  = gpio_kuka_probe, 
	.remove   = gpio_kuka_remove, 
}; 

module_platform_driver(gpio_driver_kuka);

MODULE_LICENSE("GPL"); 

原版:

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>		
#include <asm/io.h>
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/delay.h> 
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_address.h>	

struct gpio_kuka_dev
{	
	struct 	cdev 		cdev;
	struct device_node  *nd;
	struct device 		*device;
	dev_t				dev_id;
	int					major;
	unsigned int		gpio;
	int					gpio_enable_value;
};

static struct gpio_kuka_dev *gpio_kuka;
static struct class * gpio_kuka_class;
static int first_read = 1;
static int gpio_kuka_open(struct inode *inode, struct file *pfile) 
{ 
	int ret = 0;
	struct gpio_kuka_dev * dev = container_of(inode->i_cdev, struct gpio_kuka_dev, cdev);
	pfile->private_data = dev;
	
	return ret;
} 

static ssize_t gpio_kuka_read(struct file *pfile, char __user *buf, size_t size, loff_t *offset) 
{ 
	int ret = 0;
	struct gpio_kuka_dev *p;
	char level_str[3] = {0};
	int level = 0;
	p = pfile->private_data;

	level = gpio_get_value(p->gpio);
	sprintf(level_str,"%d\n",level);
	ret = copy_to_user(buf, level_str, sizeof(level_str));
	if(first_read)
	{
		first_read = 0;
		return sizeof(level_str);
	}
	else
	{
		first_read = 1;
		return 0;
	}
} 

static ssize_t gpio_kuka_write(struct file *pfile, const char __user *buf, size_t size, loff_t *offset) 
{ 
	int ret = 0;
	struct gpio_kuka_dev *p;
	char level_str[2] = {0};
	int level = 0;
	
	p = pfile->private_data;
	if(size > 2)
	{
		printk("invalid param\n");
		return -1;
	}
	ret = copy_from_user(&level_str, buf, size);
	level = simple_strtol(level_str, NULL, 10);
	if(level != 0 && level != 1)
	{
		printk("invalid param\n");
		return -1;
	}
	gpio_set_value(p->gpio, level);
	printk("gpio set value %d\n",level);
    return size;
} 

static struct file_operations gpio_kuka_fops = { 
     .owner = THIS_MODULE, 
     .open  = gpio_kuka_open,
     .read  = gpio_kuka_read,
     .write = gpio_kuka_write, 
};   

static struct of_device_id of_gpio_kuka_ids[] = {
   {.compatible = "gpio_kuka"},
   { }   
 };

static int gpio_kuka_probe(struct platform_device *pdev)  
{
	int gpio;
	enum of_gpio_flags flag;
	struct device_node *kuka_gpio_node = pdev->dev.of_node;
   	gpio_kuka = devm_kzalloc(&pdev->dev,sizeof(struct gpio_kuka_dev), GFP_KERNEL);
   	if (!gpio_kuka) {
        return -ENOMEM;
    }
	gpio = of_get_named_gpio_flags(kuka_gpio_node, "gpio_kuka", 0, &flag);
	if (!gpio_is_valid(gpio)) {
		printk("kuka-gpio: %d is invalid\n", gpio); return -ENODEV;
    }
	if (gpio_request(gpio, "gpio_kuka")) {
        printk("gpio %d request failed!\n", gpio);
        gpio_free(gpio);
        return -ENODEV;
    }
	gpio_kuka->gpio = gpio;
	gpio_kuka->nd =  pdev->dev.of_node;
    gpio_kuka->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
   	gpio_direction_output(gpio_kuka->gpio, gpio_kuka->gpio_enable_value);
    printk("kuka gpio putout\n");

	alloc_chrdev_region(&gpio_kuka->dev_id, 0, 1, pdev->name);
	gpio_kuka->major = MAJOR(gpio_kuka->dev_id);
   	cdev_init(&gpio_kuka->cdev, &gpio_kuka_fops);
	cdev_add(&gpio_kuka->cdev, gpio_kuka->dev_id, 1);
	gpio_kuka_class = class_create(THIS_MODULE, pdev->name);
	gpio_kuka->device = device_create(gpio_kuka_class, NULL, gpio_kuka->dev_id, NULL, pdev->name);
	gpio_kuka->device->gpio = gpio_kuka->gpio;
	
   	return 0; 
} 
  
static int gpio_kuka_remove(struct platform_device *pdev) 
{
	gpio_free(gpio_kuka->gpio);
	cdev_del(&gpio_kuka->cdev);
	unregister_chrdev_region(gpio_kuka->dev_id, 1);
	devm_kfree(&pdev->dev, gpio_kuka);
	return 0; 
} 

static struct platform_driver gpio_driver_kuka = { 
	.driver   = { 
	.owner    = THIS_MODULE, 
	.name     = "gpio_kuka",
	.of_match_table = of_match_ptr(of_gpio_kuka_ids),
	}, 
	.probe 	  = gpio_kuka_probe, 
	.remove   = gpio_kuka_remove, 
}; 

module_platform_driver(gpio_driver_kuka);

MODULE_LICENSE("GPL"); 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值