Project

General

Profile

RE: FPGA GPIO interrupt » fpga_uinput.c

V J, 12/21/2017 08:47 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
#define UINPUT_BASE 0xff200000
15
#define UINPUT_SIZE PAGE_SIZE
16
//#define UINPUT_INT_NUM 72
17
#define UINPUT_INT_NUM 396   //insmod: ERROR: could not insert module fpga_uinput.ko: Device or resource busy
18

    
19
void *fpga_uinput_mem;
20

    
21
static DEFINE_SEMAPHORE(interrupt_mutex);
22
static DECLARE_WAIT_QUEUE_HEAD(interrupt_wq);
23

    
24
static int interrupt_flag = 0;
25
static DEFINE_SPINLOCK(interrupt_flag_lock);
26
static uint8_t input_state;
27
//static int irq_cnt = 0;
28

    
29
static irqreturn_t fpga_uinput_interrupt(int irq, void *dev_id)
30
{
31
   if (irq != UINPUT_INT_NUM)
32
   {
33
      return IRQ_NONE;
34
   }
35
   spin_lock(&interrupt_flag_lock);
36
   interrupt_flag = 1;
37
   input_state = ioread8(fpga_uinput_mem);
38
   spin_unlock(&interrupt_flag_lock);
39

    
40
   wake_up_interruptible(&interrupt_wq);
41

    
42
   return IRQ_HANDLED;
43
}
44

    
45
static struct device_driver fpga_uinput_driver = {
46
   .name = "fpga_uinput",
47
   .bus = &platform_bus_type,
48
};
49

    
50
static ssize_t fpga_uinput_show(struct device_driver *drv, char *buf)
51
{
52
   int ret;
53
   if (down_trylock(&interrupt_mutex))
54
   {
55
      printk(KERN_ALERT "1: KERNEL DEBUG down_trylock: Passed %s %d \n",__FUNCTION__,__LINE__);             
56
      return -EAGAIN;
57
   }
58

    
59
   if (wait_event_interruptible(interrupt_wq, interrupt_flag != 0)) {
60
      ret = -ERESTART;
61
      printk(KERN_ALERT "2: KERNEL DEBUG release_and_exit: Passed %s %d \n",__FUNCTION__,__LINE__);         
62
      goto release_and_exit;
63
   }
64

    
65
   spin_lock(&interrupt_flag_lock);
66
   interrupt_flag = 0;
67
   spin_unlock(&interrupt_flag_lock);
68

    
69
   buf[0] = input_state;
70
   ret = 1;
71

    
72
release_and_exit:
73
   up(&interrupt_mutex);
74
   return ret;
75
}
76

    
77
static ssize_t fpga_uinput_store(struct device_driver *drv,
78
      const char *buf, size_t count)
79
{
80
   return -EROFS;
81
}
82

    
83
static DRIVER_ATTR(fpga_uinput, S_IRUSR, fpga_uinput_show, fpga_uinput_store);
84

    
85
static int __init fpga_uinput_init(void)
86
{
87
   int ret;
88
   struct resource *res;
89

    
90
    printk(KERN_ALERT "3: KERNEL DEBUG fpga_uinput_init: Passed %s %d \n",__FUNCTION__,__LINE__);  
91
   ret = driver_register(&fpga_uinput_driver);
92
   if (ret < 0)
93
      goto fail_driver_register;
94

    
95
   ret = driver_create_file(&fpga_uinput_driver,
96
         &driver_attr_fpga_uinput);
97
   if (ret < 0)
98
      goto fail_create_file;
99

    
100
   res = request_mem_region(UINPUT_BASE, UINPUT_SIZE, "fpga_uinput");
101
   if (res == NULL) {
102
      ret = -EBUSY;
103
      goto fail_request_mem;
104
   }
105

    
106
   fpga_uinput_mem = ioremap(UINPUT_BASE, UINPUT_SIZE);
107
   if (fpga_uinput_mem == NULL) {
108
      ret = -EFAULT;
109
      goto fail_ioremap;
110
   }
111

    
112
   ret = request_irq(UINPUT_INT_NUM, fpga_uinput_interrupt,
113
         0, "fpga_uinput", NULL);
114
   if (ret < 0)
115
      goto fail_request_irq;
116

    
117
   return 0;
118

    
119
fail_request_irq:
120
   iounmap(fpga_uinput_mem);
121
fail_ioremap:
122
   release_mem_region(UINPUT_BASE, UINPUT_SIZE);
123
fail_request_mem:
124
   driver_remove_file(&fpga_uinput_driver, &driver_attr_fpga_uinput);
125
fail_create_file:
126
   driver_unregister(&fpga_uinput_driver);
127
fail_driver_register:
128
   return ret;
129
}
130

    
131
static void __exit fpga_uinput_exit(void)
132
{
133
   free_irq(UINPUT_INT_NUM, NULL);
134
   iounmap(fpga_uinput_mem);
135
   release_mem_region(UINPUT_BASE, UINPUT_SIZE);
136
   driver_remove_file(&fpga_uinput_driver, &driver_attr_fpga_uinput);
137
   driver_unregister(&fpga_uinput_driver);
138
}
139

    
140
MODULE_LICENSE("Dual BSD/GPL");
141

    
142
module_init(fpga_uinput_init);
143
module_exit(fpga_uinput_exit);
(1-1/4) Go to top
Add picture from clipboard (Maximum size: 1 GB)