Project

General

Profile

RE: FPGA PIO interrupt issues with Rocko and kernel 4.9 » fpga_uinput0.c

V J, 06/28/2019 10:04 AM

 
1
#include <linux/init.h>
2
#include <linux/module.h>
3
#include <linux/kernel.h>
4
#include <linux/device.h>
5
#include <linux/platform_device.h>
6
#include <linux/ioport.h>
7
#include <linux/io.h>
8
#include <linux/wait.h>
9
#include <linux/sched.h>
10
#include <linux/semaphore.h>
11
#include <linux/interrupt.h>
12
#include <linux/spinlock_types.h>
13
//
14
#include <linux/irq.h>
15
#include <linux/gpio.h>
16

    
17
#define UINPUT_BASE 0xff2000a0  //fpga_irq address
18
#define UINPUT_SIZE 0x10
19

    
20
#define UINPUT_INT_NUM 352      
21

    
22
static int gpio_number = UINPUT_INT_NUM;     
23

    
24
void *fpga_uinput_mem;
25

    
26
static DEFINE_SEMAPHORE(interrupt_mutex);
27
static DECLARE_WAIT_QUEUE_HEAD(interrupt_wq);
28

    
29
static int interrupt_flag = 0;
30
static DEFINE_SPINLOCK(interrupt_flag_lock);
31
static uint8_t input_state;
32

    
33
static irqreturn_t fpga_uinput_interrupt(int irq, void *dev_id)
34
{
35
   int irq_number;
36
   irq_number = gpio_to_irq(gpio_number);
37
   if (irq != irq_number)
38
   {
39
      printk(KERN_ALERT "irq != UINPUT_INT_NUM: Passed %s %d \n", __FUNCTION__, __LINE__);
40
      return IRQ_NONE;
41
   }
42

    
43
   spin_lock(&interrupt_flag_lock);
44
   interrupt_flag = 1;
45
   input_state = ioread8(fpga_uinput_mem);
46
   spin_unlock(&interrupt_flag_lock);
47

    
48
   wake_up_interruptible(&interrupt_wq);
49

    
50
   return IRQ_HANDLED;
51
}
52

    
53
static struct device_driver fpga_uinput_driver = {
54
   .name = "fpga_uinput0",
55
   .bus = &platform_bus_type,
56
};
57

    
58
static ssize_t fpga_uinput_show(struct device_driver *drv, char *buf)
59
{
60
   int ret;
61

    
62
   if (down_trylock(&interrupt_mutex))
63
      return -EAGAIN;
64

    
65
   if (wait_event_interruptible(interrupt_wq, interrupt_flag != 0))
66
   {
67
      ret = -ERESTART;
68
      goto release_and_exit;
69
   }
70

    
71
   spin_lock(&interrupt_flag_lock);
72
   interrupt_flag = 0;
73
   spin_unlock(&interrupt_flag_lock);
74

    
75
   buf[0] = input_state;
76
   ret = 1;
77

    
78
   release_and_exit:
79
   up(&interrupt_mutex);
80
   return ret;
81
}
82

    
83
static ssize_t fpga_uinput_store(struct device_driver *drv, const char *buf, size_t count)
84
{
85
   return -EROFS;
86
}
87

    
88
static DRIVER_ATTR(fpga_uinput, S_IRUSR, fpga_uinput_show, fpga_uinput_store);
89

    
90
static int __init fpga_uinput_init(void)
91
{
92
   int ret;
93
   int irq_number;
94
   struct resource *res;
95

    
96
   ret = driver_register(&fpga_uinput_driver);
97
   if (ret < 0)
98
      goto fail_driver_register;
99

    
100
   ret = driver_create_file(&fpga_uinput_driver, &driver_attr_fpga_uinput);
101
   if (ret < 0)
102
      goto fail_create_file;
103

    
104
   res = request_mem_region(UINPUT_BASE, UINPUT_SIZE, "fpga_uinput0");
105
   if (res == NULL)
106
   {
107
      ret = -EBUSY;
108
      goto fail_request_mem;
109
   }
110

    
111
   fpga_uinput_mem = ioremap(UINPUT_BASE, UINPUT_SIZE);
112
   if (fpga_uinput_mem == NULL)
113
   {
114
      ret = -EFAULT;
115
      goto fail_ioremap;
116
   }
117

    
118
   irq_number = gpio_to_irq(gpio_number);
119
   ret = request_irq(irq_number, fpga_uinput_interrupt, 0, "fpga_uinput0", NULL);
120
   if (ret < 0)
121
      goto fail_request_irq;
122

    
123
   return 0;
124

    
125
 fail_request_irq:
126
   iounmap(fpga_uinput_mem);
127
   printk(KERN_ALERT "DEBUG: fail_request_irq: Passed %s %d \n", __FUNCTION__, __LINE__);
128
 fail_ioremap:
129
   release_mem_region(UINPUT_BASE, UINPUT_SIZE);
130
   printk(KERN_ALERT "DEBUG: fail_ioremap: Passed %s %d \n", __FUNCTION__, __LINE__);
131
 fail_request_mem:
132
   driver_remove_file(&fpga_uinput_driver, &driver_attr_fpga_uinput);
133
   printk(KERN_ALERT "DEBUG: fail_request_mem: Passed %s %d \n", __FUNCTION__, __LINE__);
134
 fail_create_file:
135
   driver_unregister(&fpga_uinput_driver);
136
   printk(KERN_ALERT "DEBUG: fail_create_file: Passed %s %d \n", __FUNCTION__, __LINE__);
137
 fail_driver_register:
138
   printk(KERN_ALERT "DEBUG: fail_driver_register: Passed %s %d \n", __FUNCTION__, __LINE__);
139
   return ret;
140
}
141

    
142
static void __exit fpga_uinput_exit(void)
143
{
144
   free_irq(gpio_to_irq(gpio_number), NULL);
145
   iounmap(fpga_uinput_mem);
146
   release_mem_region(UINPUT_BASE, UINPUT_SIZE);
147
   driver_remove_file(&fpga_uinput_driver, &driver_attr_fpga_uinput);
148
   driver_unregister(&fpga_uinput_driver);
149
}
150

    
151
MODULE_LICENSE("Dual BSD/GPL");
152

    
153
module_init(fpga_uinput_init);
154
module_exit(fpga_uinput_exit);
(2-2/2) Go to top
Add picture from clipboard (Maximum size: 1 GB)