raspi_gpio_driver

view gpio.c @ 2:a7543d592206

- interrupt debouncing (crude) - blinking another led when pressing the button - using broadcom custom pullup/down function
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 05 Mar 2016 04:55:03 +0000
parents acfcd119e532
children
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>
8 #include <linux/jiffies.h>
9 #include <linux/platform_data/bcm2708.h>
11 #define TEST_OUTPUT_PIN 4
12 #define TEST_OUTPUT_GREEN 17
13 #define TEST_INPUT_PIN 22
15 static int dev_init(void);
16 static void dev_exit(void);
17 static int dev_open(struct inode *inode, struct file *file);
18 static int dev_close(struct inode *inode, struct file *file);
19 static ssize_t dev_write(struct file *file, const char *buf, size_t sz, loff_t *offset);
21 static irqreturn_t intr_handler(int inum, void *devid, struct pt_regs *regs);
23 MODULE_LICENSE("GPL");
24 MODULE_AUTHOR("John Tsiombikas");
25 MODULE_DESCRIPTION("gpio module");
27 module_init(dev_init);
28 module_exit(dev_exit);
30 static int major;
31 static int intr_num = -1;
32 static int num_presses;
34 static struct file_operations ops = {
35 .open = dev_open,
36 .release = dev_close,
37 .write = dev_write
38 };
40 static int dev_init(void)
41 {
42 if((major = register_chrdev(0, "gpio", &ops)) < 0) {
43 printk("failed to register character device gpio (err: %d)\n", major);
44 return -1;
45 }
46 printk("gpio module registered (device: %d)\n", major);
48 gpio_direction_output(TEST_OUTPUT_PIN, 0);
49 gpio_direction_output(TEST_OUTPUT_GREEN, 0);
51 if(gpio_request(TEST_INPUT_PIN, "test_input") != 0) {
52 printk("gpio: failed to get input gpio pin\n");
53 return -1;
54 }
55 gpio_direction_input(TEST_INPUT_PIN);
56 bcm2708_gpio_setpull(gpio_to_chip(TEST_INPUT_PIN), TEST_INPUT_PIN, BCM2708_PULL_DOWN);
57 if((intr_num = gpio_to_irq(TEST_INPUT_PIN)) < 0) {
58 printk("gpio: failed to get interrupt line for gpio pin\n");
59 return -1;
60 }
61 if(request_irq(intr_num, (irq_handler_t)intr_handler, IRQF_TRIGGER_RISING,
62 "gpio_intr", "gpio") != 0) {
63 printk("gpio: failed to setup interrupt handler\n");
64 return -1;
65 }
67 return 0;
68 }
70 static void dev_exit(void)
71 {
72 printk("gpio exit\n");
74 unregister_chrdev(major, "gpio");
76 if(intr_num != -1) {
77 free_irq(intr_num, "gpio");
78 }
79 gpio_free(TEST_INPUT_PIN);
81 gpio_direction_input(TEST_OUTPUT_PIN);
82 gpio_direction_input(TEST_OUTPUT_GREEN);
83 bcm2708_gpio_setpull(gpio_to_chip(TEST_INPUT_PIN), TEST_INPUT_PIN, BCM2708_PULL_OFF);
84 }
86 static int dev_open(struct inode *inode, struct file *file)
87 {
88 try_module_get(THIS_MODULE);
89 return 0;
90 }
92 static int dev_close(struct inode *inode, struct file *file)
93 {
94 module_put(THIS_MODULE);
95 return 0;
96 }
98 static ssize_t dev_write(struct file *file, const char *buf, size_t sz, loff_t *offset)
99 {
100 unsigned char val;
102 if(sz < 1) {
103 return 0;
104 }
105 if(copy_from_user(&val, (unsigned char*)buf + sz - 1, 1) != 0) {
106 return -EFAULT;
107 }
109 gpio_set_value(TEST_OUTPUT_PIN, val == '0' ? 0 : 1);
110 return sz;
111 }
113 static irqreturn_t intr_handler(int inum, void *devid, struct pt_regs *regs)
114 {
115 static unsigned long ignore_until;
116 unsigned long now = jiffies;
118 if(time_before(now, ignore_until)) {
119 return IRQ_HANDLED;
120 }
121 ignore_until = now + 128 * HZ / 1000;
123 printk("presses: %d\n", num_presses++);
124 gpio_set_value(TEST_OUTPUT_GREEN, num_presses & 1);
125 return IRQ_HANDLED;
126 }