#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <gpio.h>
#include <soc/gpio.h>
#define JT_GPIO_MAGIC ('k')
#define JT_GPIO_READ _IO(JT_GPIO_MAGIC, 1)
#define JT_GPIO_WRITE _IO(JT_GPIO_MAGIC, 2)
#define WAKEUP_PIN GPIO_PB(28)
MODULE_AUTHOR("Bing <Bing.cromie@gmail.com>");
MODULE_DESCRIPTION("JT WAKEUP GPIO Pin Driver");
MODULE_LICENSE("GPL");
static int major;
static struct class *jt_gpio_class;
static struct device *jt_gpio_device;
static int jt_gpio_open(struct inode *inode, struct file *file)
{
return 0;
}
static int jt_gpio_release(struct inode *inode, struct file *file)
{
return 0;
}
static long jt_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int value;
get_user(value, (int *)arg);
switch (cmd) {
case JT_GPIO_WRITE:
gpio_set_value(WAKEUP_PIN, value);
break;
default:
printk(KERN_INFO "unsupported cmd\n");
return -1;
}
return 0;
}
const struct file_operations jt_gpio_fops = {
.owner = THIS_MODULE,
.open = jt_gpio_open,
.release = jt_gpio_release,
.unlocked_ioctl = jt_gpio_ioctl,
};
static int __init jt_gpio_init(void)
{
int ret;
ret = gpio_request_one(WAKEUP_PIN, GPIOF_DIR_OUT, "JT_WAKEUP");
if (ret) {
printk(KERN_INFO "gpio_request wakeup pin fail\n");
return -1;
}
ret = gpio_direction_output(WAKEUP_PIN, 0);
if (ret) {
printk(KERN_INFO "gpio as output pin fail\n");
return -1;
}
major = register_chrdev(0, "jt_gpio", &jt_gpio_fops);
jt_gpio_class = class_create(THIS_MODULE, "jt_gpio_class");
if (!jt_gpio_class) {
printk(KERN_INFO "jt_gpio class_create fail\n");
return -1;
}
jt_gpio_device = device_create(jt_gpio_class, NULL, MKDEV(major, 0), NULL, "jt_gpio");
if (!jt_gpio_device) {
printk(KERN_INFO "jt_gpio device_create fail\n");
return -1;
}
return 0;
}
static void __exit jt_gpio_exit(void)
{
gpio_free(WAKEUP_PIN);
unregister_chrdev(major, "jt_gpio");
device_unregister(jt_gpio_device);
class_destroy(jt_gpio_class);
}
module_init(jt_gpio_init);
module_exit(jt_gpio_exit);
内核关于gpio驱动有标准接口,一般是申请gpio,设置gpio是输入还是输出,接着设置gpio的值,使用结束撤销申请
本例将gpio注册为一个字符设备,并将其信息导出到sys文件系统,这样当系统启动udev后会自动创建设备节点,
从而省去手动创建的麻烦.
下面是应用测试程序:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#define HELLO_MAGIC 'k'
#define GPIO_READ _IO (HELLO_MAGIC, 1)
#define GPIO_WRITE _IO (HELLO_MAGIC, 2)
int main(int argc, char** argv)
{
int fd;
int ret = 0;
int value = 0;
if (argc != 2) {
printf("usage : ./a.out value\n");
exit(-1);
}
value = atoi(argv[1]);
fd = open("/dev/jt_gpio",O_RDWR);
if (fd < 0) {
printf ("open wakup gpio fail\n");
return -1;
}
ret = ioctl (fd, GPIO_WRITE,&value);
if (ret < 0) {
close(fd);
printf("set wakeup pin to %d fail \n", value);
return -1;
}
close (fd);
return 0;
}