最近用到了am3352 linux gpio 的驱动贴出来一起共勉。
有瑕疵请留言哦。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gpio.h"
struct gpio_info {
u32 pin;
char pin_name[20];
struct miscdevice *pmiscdev;
};
static struct gpio_info *gpio_info_file[255];
static struct gpio_info *all_gpios_info;
static struct gpio_info all_gpios_info_am3352[] ={
{41, "touct", NULL},
{40, "voice", NULL},
{0, "", NULL}, //the end
};
static int gpio_open(struct inode *inode, struct file *filp);
static int gpio_release(struct inode *inode, struct file *filp);
ssize_t gpio_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos);
static long gpio_ioctl(struct file *flip, unsigned command, unsigned long arg);
static int gpio_init(void);
static void gpio_exit(void);
static int gpio_open(struct inode *inode, struct file *filp)
{
struct gpio_info *gpio_info_tmp;
u32 minor = iminor(inode);
gpio_info_tmp = kmalloc(sizeof(struct gpio_info), GFP_KERNEL);
gpio_info_tmp = gpio_info_file[minor];
filp->private_data = gpio_info_tmp ;
gpio_free(gpio_info_tmp->pin);
printk("gpio num= %d\n",gpio_info_tmp->pin);
if (gpio_request(gpio_info_tmp->pin, gpio_info_tmp->pin_name)) {
printk("request %s gpio faile \n", gpio_info_tmp->pin_name);
return -1;
}
return 0;
}
static int gpio_release(struct inode *inode, struct file *filp)
{
struct gpio_info *gpio_info_tmp = (struct gpio_info *)filp->private_data;
gpio_free(gpio_info_tmp->pin);
return 0;
}
ssize_t gpio_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
struct gpio_info *gpio_info_tmp = (struct gpio_info *)filp->private_data;
char data[2];
printk("make: %s \n", gpio_info_tmp->pin_name);
if(!copy_from_user(data, buf, 2))
{
data[0] = data[0] - '0';
if (data[0] == 1 || data[0] == 0) {
gpio_direction_output(gpio_info_tmp->pin, data[0]);
}
return count;
}
else
{
return -1;
}
}
static ssize_t gpio_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct gpio_info *gpio_info_tmp = (struct gpio_info *)file->private_data;
char data[2];
gpio_direction_input(gpio_info_tmp->pin);
data[0] = gpio_get_value(gpio_info_tmp->pin);
data[0] = data[0] ? 1 : 0;
data[0] = data[0] + '0';
data[1] = '\n';
if(!copy_to_user(buf,data,2))
{
return 0;
}
else
{
return -1;
}
}
static long gpio_ioctl(struct file *flip, unsigned command, unsigned long arg)
{
//printk("ioctl \n");
struct gpio_info *gpio_info_tmp = (struct gpio_info *)flip->private_data;
int data = 0;
//printk("cmd = %d \n",command);
switch (command) {
case SET_GPIO_HIGHT:
gpio_direction_output(gpio_info_tmp->pin, 1);
break;
case SET_GPIO_LOW:
gpio_direction_output(gpio_info_tmp->pin, 0);
break;
case GET_GPIO_VALUE:
gpio_direction_input(gpio_info_tmp->pin);
data = gpio_get_value(gpio_info_tmp->pin);
data = data ? 1 : 0;
//copy_to_user((void *)arg, (void *)(&data), sizeof(int));
if(copy_to_user((void *)arg, (void *)(&data), sizeof(int)))
{
return -1;
}
break;
default:
printk("cmd error \n");
return -1;
}
return 0;
}
static struct file_operations gpio_fops={
.owner = THIS_MODULE,
.unlocked_ioctl = gpio_ioctl,
.open = gpio_open,
.write = gpio_write,
.read = gpio_read,
.release = gpio_release,
};
static int __init gpio_init(void)
{
int i = 0;
int ret = 0;
all_gpios_info = all_gpios_info_am3352;
for (i = 0; all_gpios_info[i].pin != 0; i++) {
all_gpios_info[i].pmiscdev = kmalloc(sizeof(struct miscdevice), GFP_KERNEL);
if (all_gpios_info[i].pmiscdev == NULL) {
printk("unable to malloc memory \n");
return -1;
}
memset(all_gpios_info[i].pmiscdev, 0, sizeof(struct miscdevice));
all_gpios_info[i].pmiscdev->name = all_gpios_info[i].pin_name;
all_gpios_info[i].pmiscdev->fops = &gpio_fops;
all_gpios_info[i].pmiscdev->minor = MISC_DYNAMIC_MINOR;
ret = misc_register(all_gpios_info[i].pmiscdev);
if (ret) {
printk("misc regist faile \n");
return -1;
}
gpio_info_file[all_gpios_info[i].pmiscdev->minor] = &(all_gpios_info[i]);
printk("build device i:%d dev:/dev/%s \n", i, all_gpios_info[i].pmiscdev->name);
}
return 0;
}
static void __exit gpio_exit(void)
{
int i = 0;
for (i = 0; all_gpios_info[i].pin != 0; i++) {
misc_deregister(all_gpios_info[i].pmiscdev);
}
printk("gpio driver down.\n");
}
module_init(gpio_init);
module_exit(gpio_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("liusongnian");
MODULE_DESCRIPTION("GPIO DRIVER FOR am3352");