2 * file: rpi_gpio_irc_module.c
4 * Driver for processing events on GPIO inputs and evaluation
5 * quadrature encoded signals to position value
7 * Copyright (C) 2014 Radek Meciar
8 * Copyright (C) 2014 Pavel Pisa
10 * More information in bachelor thesis
11 * Motor control with Raspberry Pi board and Linux
12 * https://support.dce.felk.cvut.cz/mediawiki/images/1/10/Bp_2014_meciar_radek.pdf
13 * Supervisor: Pavel Pisa <pisa@cmp.felk.cvut.cz>
15 * This file is subject to the terms and conditions of the GNU General Public
16 * License. See the file COPYING in the main directory of this archive
21 IRC inputs are mapped to GPIO 7, 8, 23, 24 on RPI P1.
22 The channel A is mapped to inputs 7 and 8, channel B to 23 and 24.
23 Mapping of each signal to two inputs (one configured for IRQ on
24 signal rising edge and another for falling edge)
25 simplifies evaluation because there is no need to read actual
26 GPIO values which posses considerable overhead through
27 Linux generic GPIO infrastructue.
30 #include <linux/init.h>
31 #include <linux/module.h>
32 #include <linux/gpio.h>
33 #include <linux/interrupt.h>
34 #include <linux/proc_fs.h>
35 #include <linux/uaccess.h>
36 #include <linux/device.h>
38 #define IRC1_GPIO 23 /* GPIO 3 -> IRC channel A */
42 #define IRC2_GPIO 25 /* GPIO 2 -> IRC channel B */
45 #define IRC2_GPIO 7 /* GPIO 2 -> IRC channel B */
49 /* #define IRQ_GPIO 25 input not used for this variant of processing */
51 #define IRC1_NAME "GPIO23_irc1_chA"
52 #define IRC2_NAME "GPIO7_irc2_chB"
53 #define IRC3_NAME "GPIO24_irc3_chA"
54 #define IRC4_NAME "GPI08_irc4_chB"
55 /* #define IRQ_name "GPIO23_irq" not used */
57 #define IRC_DIRECTION_DOWN -1
58 #define IRC_DIRECTION_UP 1
60 #define IRC_INPUT_LOW 0
62 #define DEVICE_NAME "irc"
64 struct gpio_irc_state {
66 volatile uint32_t position;
68 volatile char prev_phase;
69 volatile char direction;
73 const char *irc_gpio_name[4];
75 unsigned int irc_irq_num[4];
78 struct gpio_irc_state gpio_irc_0 = {
79 .irc_gpio = {IRC1_GPIO, IRC2_GPIO, IRC3_GPIO, IRC4_GPIO},
80 .irc_gpio_name = {IRC1_NAME, IRC2_NAME, IRC3_NAME, IRC4_NAME},
85 static struct class *irc_class;
89 * GPIO IRC 1 (= 3) rising edge handler - direction determined from IRC 2 (= 4).
91 static irqreturn_t irc_irq_handlerAR(int irq, void *dev)
93 struct gpio_irc_state *ircst = (struct gpio_irc_state *)dev;
95 if (ircst->prev_phase == 0) {
97 ircst->prev_phase = 1;
98 ircst->direction = IRC_DIRECTION_UP;
101 if (ircst->prev_phase == 3) {
103 ircst->prev_phase = 2;
104 ircst->direction = IRC_DIRECTION_DOWN;
108 if (gpio_get_value(ircst->irc_gpio[1]) == IRC_INPUT_LOW) {
110 ircst->prev_phase = 1;
111 ircst->direction = IRC_DIRECTION_UP;
114 ircst->prev_phase = 2;
115 ircst->direction = IRC_DIRECTION_DOWN;
122 * GPIO IRC 3 (= 1) faling edge handler - direction determined from IRC 2 (= 4).
124 static irqreturn_t irc_irq_handlerAF(int irq, void *dev)
126 struct gpio_irc_state *ircst = (struct gpio_irc_state *)dev;
128 if (ircst->prev_phase == 2) {
130 ircst->prev_phase = 3;
131 ircst->direction = IRC_DIRECTION_UP;
134 if (ircst->prev_phase == 1) {
136 ircst->prev_phase = 0;
137 ircst->direction = IRC_DIRECTION_DOWN;
141 if (gpio_get_value(ircst->irc_gpio[1]) != IRC_INPUT_LOW) {
143 ircst->prev_phase = 3;
144 ircst->direction = IRC_DIRECTION_UP;
147 ircst->prev_phase = 0;
148 ircst->direction = IRC_DIRECTION_DOWN;
155 * GPIO IRC 2 (= 4) falling edge handler - direction determined from IRC 1 (= 3).
157 static irqreturn_t irc_irq_handlerBF(int irq, void *dev)
159 struct gpio_irc_state *ircst = (struct gpio_irc_state *)dev;
161 if (ircst->prev_phase == 3) {
163 ircst->prev_phase = 0;
164 ircst->direction = IRC_DIRECTION_UP;
167 if (ircst->prev_phase == 2) {
169 ircst->prev_phase = 1;
170 ircst->direction = IRC_DIRECTION_DOWN;
174 if (gpio_get_value(ircst->irc_gpio[0]) == IRC_INPUT_LOW) {
176 ircst->prev_phase = 0;
177 ircst->direction = IRC_DIRECTION_UP;
180 ircst->prev_phase = 1;
181 ircst->direction = IRC_DIRECTION_DOWN;
188 * GPIO IRC 4 (= 2) rising edge handler - direction determined from IRC 1 (= 3).
190 static irqreturn_t irc_irq_handlerBR(int irq, void *dev)
192 struct gpio_irc_state *ircst = (struct gpio_irc_state *)dev;
194 if (ircst->prev_phase == 1) {
196 ircst->prev_phase = 2;
197 ircst->direction = IRC_DIRECTION_UP;
200 if (ircst->prev_phase == 0) {
202 ircst->prev_phase = 3;
203 ircst->direction = IRC_DIRECTION_DOWN;
207 if (gpio_get_value(ircst->irc_gpio[0]) != IRC_INPUT_LOW) {
209 ircst->prev_phase = 2;
210 ircst->direction = IRC_DIRECTION_UP;
213 ircst->prev_phase = 3;
214 ircst->direction = IRC_DIRECTION_DOWN;
221 * file operation processing read systemcall for /dev/irc0 device
222 * it returns accumulated position to the calling process buffer
224 ssize_t irc_read(struct file *file, char *buffer, size_t length, loff_t *offset)
226 struct gpio_irc_state *ircst = (struct gpio_irc_state *)file->private_data;
231 if (length < sizeof(uint32_t)) {
232 pr_debug("Trying to read less bytes than a irc message,\n");
233 pr_debug("this will always return zero.\n");
237 pos = ircst->position;
239 ret = copy_to_user(buffer, &pos, sizeof(uint32_t));
241 buffer += sizeof(uint32_t);
243 bytes_to_copy = length-sizeof(uint32_t);
247 return length - bytes_to_copy;
252 * file operation called at /dev/irc0 device open
253 * it records number of active device users
255 int irc_open(struct inode *inode, struct file *file)
257 int dev_minor = MINOR(inode->i_rdev);
258 struct gpio_irc_state *ircst = &gpio_irc_0;
261 pr_err("There is no hardware support for the device file with minor nr.: %d\n",
264 atomic_inc(&ircst->used_count);
266 file->private_data = ircst;
272 * file operation called at /dev/irc0 device close/release time
274 int irc_relase(struct inode *inode, struct file *file)
276 struct gpio_irc_state *ircst = (struct gpio_irc_state *)file->private_data;
278 if (atomic_dec_and_test(&ircst->used_count))
279 pr_debug("Last irc user finished\n");
285 *Define file operations for device IRC
287 const struct file_operations irc_fops = {
288 .owner = THIS_MODULE,
291 /* .poll = irc_poll,*/
293 .release = irc_relase,
296 void gpio_irc_free_irq_fn(struct gpio_irc_state *ircst)
300 for (i = 0; i < 4; i++)
301 free_irq(ircst->irc_irq_num[i], ircst);
304 void gpio_irc_free_fn(struct gpio_irc_state *ircst)
308 for (i = 0; i < 4; i++)
309 gpio_free(ircst->irc_gpio[i]);
313 * gpio_irc_setup_inputs:
314 * Configure inputs as sources and connect interrupt handlers
315 * GPIO 2, 3, 4, 23 and 24 are configured as inputs
317 int gpio_irc_setup_inputs(struct gpio_irc_state *ircst)
321 for (i = 0; i < 4; i++) {
322 if (gpio_request(ircst->irc_gpio[i], ircst->irc_gpio_name[i]) != 0) {
323 pr_err("failed request %s\n", ircst->irc_gpio_name[i]);
324 goto error_gpio_request;
328 for (i = 0; i < 4; i++) {
329 if (gpio_direction_input(ircst->irc_gpio[i]) != 0) {
330 pr_err("failed set direction input %s\n", ircst->irc_gpio_name[i]);
331 gpio_irc_free_fn(ircst);
341 gpio_free(ircst->irc_gpio[--i]);
348 * Module initialization.
350 static int gpio_irc_init(void)
356 struct gpio_irc_state *ircst = &gpio_irc_0;
357 struct device *this_dev;
359 pr_notice("gpio_irc init started\n");
360 pr_notice("variant without table (4x IRQ on 4 GPIO) - FAST\n");
361 pr_notice("for peripheral variant 2\n");
363 irc_class = class_create(THIS_MODULE, DEVICE_NAME);
364 res = register_chrdev(dev_major, DEVICE_NAME, &irc_fops);
366 pr_err("Error registering driver.\n");
367 class_destroy(irc_class);
369 /*goto register_error;*/
374 this_dev = device_create(irc_class, NULL, MKDEV(dev_major, dev_minor),
375 NULL, "irc%d", dev_minor);
377 if (IS_ERR(this_dev)) {
378 pr_err("problem to create device \"irc%d\" in the class \"irc\"\n",
383 pom = gpio_irc_setup_inputs(ircst);
385 pr_err("Inicializace GPIO se nezdarila");
389 ircst->prev_phase = -1;
391 for (i = 0; i < 4; i++) {
394 irq_num = gpio_to_irq(ircst->irc_gpio[i]);
396 pr_err("failed get IRQ number %s\n", ircst->irc_gpio_name[i]);
397 gpio_irc_free_fn(ircst);
400 ircst->irc_irq_num[i] = (unsigned int)irq_num;
403 if (request_irq(ircst->irc_irq_num[0], irc_irq_handlerAR,
404 IRQF_TRIGGER_RISING, "irc1_irqAS", ircst) != 0) {
405 pr_err("failed request IRQ for %s\n", ircst->irc_gpio_name[0]);
406 gpio_irc_free_fn(ircst);
409 if (request_irq(ircst->irc_irq_num[2], irc_irq_handlerAF,
410 IRQF_TRIGGER_FALLING, "irc3_irqAN", ircst) != 0) {
411 pr_err("failed request IRQ for %s\n", ircst->irc_gpio_name[2]);
412 free_irq(ircst->irc_irq_num[0], ircst);
413 gpio_irc_free_fn(ircst);
416 if (request_irq(ircst->irc_irq_num[1], irc_irq_handlerBF,
417 IRQF_TRIGGER_FALLING, "irc2_irqBS", ircst) != 0) {
418 pr_err("failed request IRQ for %s\n", ircst->irc_gpio_name[1]);
419 free_irq(ircst->irc_irq_num[0], ircst);
420 free_irq(ircst->irc_irq_num[2], ircst);
421 gpio_irc_free_fn(ircst);
424 if (request_irq(ircst->irc_irq_num[3], irc_irq_handlerBR,
425 IRQF_TRIGGER_RISING, "irc4_irqBN", ircst) != 0) {
426 pr_err("failed request IRQ for %s\n", ircst->irc_gpio_name[3]);
427 free_irq(ircst->irc_irq_num[0], ircst);
428 free_irq(ircst->irc_irq_num[2], ircst);
429 free_irq(ircst->irc_irq_num[1], ircst);
430 gpio_irc_free_fn(ircst);
433 pr_notice("gpio_irc init done\n");
439 * Called when module is removed.
441 static void gpio_irc_exit(void)
443 struct gpio_irc_state *ircst = &gpio_irc_0;
446 gpio_irc_free_irq_fn(ircst);
447 gpio_irc_free_fn(ircst);
448 device_destroy(irc_class, MKDEV(dev_major, dev_minor));
449 class_destroy(irc_class);
450 unregister_chrdev(dev_major, DEVICE_NAME);
452 pr_notice("gpio_irc modul closed\n");
455 module_init(gpio_irc_init);
456 module_exit(gpio_irc_exit);
458 MODULE_LICENSE("GPL");
459 MODULE_VERSION("1.1");
460 MODULE_DESCRIPTION("gpio_irc module for incremetal/quadrature signals input processing");
461 MODULE_AUTHOR("Radek Meciar");