rev |
line source |
nuclear@0
|
1 #include <linux/module.h>
|
nuclear@0
|
2 #include <linux/kernel.h>
|
nuclear@0
|
3 #include <linux/io.h>
|
nuclear@0
|
4 #include <linux/fs.h>
|
nuclear@1
|
5 #include <linux/interrupt.h>
|
nuclear@0
|
6 #include <asm/uaccess.h>
|
nuclear@1
|
7 #include <linux/gpio.h>
|
nuclear@0
|
8
|
nuclear@1
|
9 #define TEST_OUTPUT_PIN 4
|
nuclear@1
|
10 #define TEST_INPUT_PIN 22
|
nuclear@0
|
11
|
nuclear@1
|
12 static int dev_init(void);
|
nuclear@1
|
13 static void dev_exit(void);
|
nuclear@1
|
14 static int dev_open(struct inode *inode, struct file *file);
|
nuclear@1
|
15 static int dev_close(struct inode *inode, struct file *file);
|
nuclear@1
|
16 static ssize_t dev_write(struct file *file, const char *buf, size_t sz, loff_t *offset);
|
nuclear@0
|
17
|
nuclear@1
|
18 static irqreturn_t intr_handler(int inum, void *devid, struct pt_regs *regs);
|
nuclear@0
|
19
|
nuclear@0
|
20 MODULE_LICENSE("GPL");
|
nuclear@0
|
21 MODULE_AUTHOR("John Tsiombikas");
|
nuclear@0
|
22 MODULE_DESCRIPTION("gpio module");
|
nuclear@0
|
23
|
nuclear@1
|
24 module_init(dev_init);
|
nuclear@1
|
25 module_exit(dev_exit);
|
nuclear@0
|
26
|
nuclear@0
|
27 static int major;
|
nuclear@1
|
28 static int intr_num = -1;
|
nuclear@1
|
29 static int num_presses;
|
nuclear@0
|
30
|
nuclear@0
|
31 static struct file_operations ops = {
|
nuclear@1
|
32 .open = dev_open,
|
nuclear@1
|
33 .release = dev_close,
|
nuclear@1
|
34 .write = dev_write
|
nuclear@0
|
35 };
|
nuclear@0
|
36
|
nuclear@1
|
37 static int dev_init(void)
|
nuclear@0
|
38 {
|
nuclear@0
|
39 if((major = register_chrdev(0, "gpio", &ops)) < 0) {
|
nuclear@0
|
40 printk("failed to register character device gpio (err: %d)\n", major);
|
nuclear@0
|
41 return -1;
|
nuclear@0
|
42 }
|
nuclear@0
|
43 printk("gpio module registered (device: %d)\n", major);
|
nuclear@1
|
44
|
nuclear@1
|
45 gpio_direction_output(TEST_OUTPUT_PIN, 0);
|
nuclear@1
|
46 gpio_direction_input(TEST_INPUT_PIN);
|
nuclear@1
|
47
|
nuclear@1
|
48 if(gpio_request(TEST_INPUT_PIN, "test_input") != 0) {
|
nuclear@1
|
49 printk("gpio: failed to get input gpio pin\n");
|
nuclear@1
|
50 return -1;
|
nuclear@1
|
51 }
|
nuclear@1
|
52 if((intr_num = gpio_to_irq(TEST_INPUT_PIN)) < 0) {
|
nuclear@1
|
53 printk("gpio: failed to get interrupt line for gpio pin\n");
|
nuclear@1
|
54 return -1;
|
nuclear@1
|
55 }
|
nuclear@1
|
56 if(request_irq(intr_num, (irq_handler_t)intr_handler, IRQF_TRIGGER_RISING,
|
nuclear@1
|
57 "gpio_intr", "gpio") != 0) {
|
nuclear@1
|
58 printk("gpio: failed to setup interrupt handler\n");
|
nuclear@1
|
59 return -1;
|
nuclear@1
|
60 }
|
nuclear@1
|
61
|
nuclear@0
|
62 return 0;
|
nuclear@0
|
63 }
|
nuclear@0
|
64
|
nuclear@1
|
65 static void dev_exit(void)
|
nuclear@0
|
66 {
|
nuclear@1
|
67 printk("gpio exit\n");
|
nuclear@0
|
68 unregister_chrdev(major, "gpio");
|
nuclear@1
|
69
|
nuclear@1
|
70 if(intr_num != -1) {
|
nuclear@1
|
71 free_irq(intr_num, "gpio");
|
nuclear@1
|
72 }
|
nuclear@1
|
73 gpio_free(TEST_INPUT_PIN);
|
nuclear@0
|
74 }
|
nuclear@0
|
75
|
nuclear@1
|
76 static int dev_open(struct inode *inode, struct file *file)
|
nuclear@0
|
77 {
|
nuclear@0
|
78 try_module_get(THIS_MODULE);
|
nuclear@0
|
79 return 0;
|
nuclear@0
|
80 }
|
nuclear@0
|
81
|
nuclear@1
|
82 static int dev_close(struct inode *inode, struct file *file)
|
nuclear@0
|
83 {
|
nuclear@0
|
84 module_put(THIS_MODULE);
|
nuclear@0
|
85 return 0;
|
nuclear@0
|
86 }
|
nuclear@0
|
87
|
nuclear@1
|
88 static ssize_t dev_write(struct file *file, const char *buf, size_t sz, loff_t *offset)
|
nuclear@0
|
89 {
|
nuclear@0
|
90 unsigned char val;
|
nuclear@0
|
91
|
nuclear@1
|
92 printk("dev_write(%d) called\n", sz);
|
nuclear@0
|
93
|
nuclear@0
|
94 if(sz < 1) {
|
nuclear@0
|
95 return 0;
|
nuclear@0
|
96 }
|
nuclear@0
|
97 if(copy_from_user(&val, (unsigned char*)buf + sz - 1, 1) != 0) {
|
nuclear@0
|
98 return -EFAULT;
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@1
|
101 gpio_set_value(TEST_OUTPUT_PIN, val == '0' ? 0 : 1);
|
nuclear@0
|
102 return sz;
|
nuclear@0
|
103 }
|
nuclear@0
|
104
|
nuclear@1
|
105 static irqreturn_t intr_handler(int inum, void *devid, struct pt_regs *regs)
|
nuclear@0
|
106 {
|
nuclear@1
|
107 printk("presses: %d\n", num_presses++);
|
nuclear@1
|
108 return IRQ_HANDLED;
|
nuclear@0
|
109 }
|