raspi_gpio_driver
view gpio.c @ 1:acfcd119e532
- dropped all my custom i/o register fiddling in favor of the kernel gpio
functions which are already implemented by broadcom.
- added a test interrupt handler
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 05 Mar 2016 04:25:33 +0000 |
parents | fbab2b3e28da |
children | a7543d592206 |
line source
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/io.h>
4 #include <linux/fs.h>
5 #include <linux/interrupt.h>
6 #include <asm/uaccess.h>
7 #include <linux/gpio.h>
9 #define TEST_OUTPUT_PIN 4
10 #define TEST_INPUT_PIN 22
12 static int dev_init(void);
13 static void dev_exit(void);
14 static int dev_open(struct inode *inode, struct file *file);
15 static int dev_close(struct inode *inode, struct file *file);
16 static ssize_t dev_write(struct file *file, const char *buf, size_t sz, loff_t *offset);
18 static irqreturn_t intr_handler(int inum, void *devid, struct pt_regs *regs);
20 MODULE_LICENSE("GPL");
21 MODULE_AUTHOR("John Tsiombikas");
22 MODULE_DESCRIPTION("gpio module");
24 module_init(dev_init);
25 module_exit(dev_exit);
27 static int major;
28 static int intr_num = -1;
29 static int num_presses;
31 static struct file_operations ops = {
32 .open = dev_open,
33 .release = dev_close,
34 .write = dev_write
35 };
37 static int dev_init(void)
38 {
39 if((major = register_chrdev(0, "gpio", &ops)) < 0) {
40 printk("failed to register character device gpio (err: %d)\n", major);
41 return -1;
42 }
43 printk("gpio module registered (device: %d)\n", major);
45 gpio_direction_output(TEST_OUTPUT_PIN, 0);
46 gpio_direction_input(TEST_INPUT_PIN);
48 if(gpio_request(TEST_INPUT_PIN, "test_input") != 0) {
49 printk("gpio: failed to get input gpio pin\n");
50 return -1;
51 }
52 if((intr_num = gpio_to_irq(TEST_INPUT_PIN)) < 0) {
53 printk("gpio: failed to get interrupt line for gpio pin\n");
54 return -1;
55 }
56 if(request_irq(intr_num, (irq_handler_t)intr_handler, IRQF_TRIGGER_RISING,
57 "gpio_intr", "gpio") != 0) {
58 printk("gpio: failed to setup interrupt handler\n");
59 return -1;
60 }
62 return 0;
63 }
65 static void dev_exit(void)
66 {
67 printk("gpio exit\n");
68 unregister_chrdev(major, "gpio");
70 if(intr_num != -1) {
71 free_irq(intr_num, "gpio");
72 }
73 gpio_free(TEST_INPUT_PIN);
74 }
76 static int dev_open(struct inode *inode, struct file *file)
77 {
78 try_module_get(THIS_MODULE);
79 return 0;
80 }
82 static int dev_close(struct inode *inode, struct file *file)
83 {
84 module_put(THIS_MODULE);
85 return 0;
86 }
88 static ssize_t dev_write(struct file *file, const char *buf, size_t sz, loff_t *offset)
89 {
90 unsigned char val;
92 printk("dev_write(%d) called\n", sz);
94 if(sz < 1) {
95 return 0;
96 }
97 if(copy_from_user(&val, (unsigned char*)buf + sz - 1, 1) != 0) {
98 return -EFAULT;
99 }
101 gpio_set_value(TEST_OUTPUT_PIN, val == '0' ? 0 : 1);
102 return sz;
103 }
105 static irqreturn_t intr_handler(int inum, void *devid, struct pt_regs *regs)
106 {
107 printk("presses: %d\n", num_presses++);
108 return IRQ_HANDLED;
109 }