Root/Examples/drivers/IRQ/irq.c

1/*
2 * Interrupt device driver demo
3 *
4 * Author: Andres Calderon
5 * Created: September 16, 2005
6 * Copyright: (C) 2005 emQbit Ltda
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 */
14
15#include <linux/module.h> /* Needed by all modules */
16#include <linux/kernel.h> /* Needed for KERN_INFO */
17#include <linux/ioport.h>
18#include <linux/device.h>
19#include <linux/interrupt.h> /* We want an interrupt */
20#include <linux/irq.h> /* We want an interrupt */
21#include <linux/platform_device.h>
22#include <linux/fs.h>
23#include <asm/delay.h>
24#include <asm/uaccess.h>
25#include <asm/io.h>
26#include <linux/gpio.h>
27#include <asm/mach-jz4740/gpio.h>
28
29
30
31#define FPGA_IRQ_PIN JZ_GPIO_PORTC(15)
32#define FPGA_BASE 0x15000000 //FPGA_BASE (FPGA) 0x14000000 - 0x17FFFFFF //
33#define SUCCESS 0
34#define DEVICE_NAME "irq" /* Dev name as it appears in /proc/devices */
35#define BUF_LEN 80 /* Max length of the message from the device */
36
37
38  
39static int device_open(struct inode *, struct file *);
40static int device_release(struct inode *, struct file *);
41static ssize_t device_read(struct file *, char *, size_t, loff_t *);
42static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
43
44static int irq_enabled = 0;
45static int is_device_open = 0; /* Is device open? Used to prevent multiple access to device */
46static int Major;
47
48void __iomem *ioaddress;
49static unsigned int interrupt_counter = 0;
50
51static DECLARE_WAIT_QUEUE_HEAD(wq);
52
53
54struct file_operations fops = {
55  .owner = THIS_MODULE,
56  .read = device_read,
57  .write = device_write,
58  .open = device_open,
59  .release = device_release
60};
61
62
63
64static irqreturn_t irq_handler(int irq, void *dev_id)
65{
66  if(irq_enabled)
67  {
68    interrupt_counter++;
69    printk(KERN_INFO "interrupt_counter=%d\n",interrupt_counter);
70    wake_up_interruptible(&wq);
71  }
72  
73  return IRQ_HANDLED;
74}
75
76
77static int __init qem_init(void)
78{
79  int res, irq;
80  printk(KERN_INFO "FPGA module is Up.\n");
81  interrupt_counter = 0;
82         
83  Major = register_chrdev(0, DEVICE_NAME, &fops);
84  
85  if (Major < 0) {
86      printk(KERN_ALERT "Registering char device failed with %d\n", Major);
87    return Major;
88  }
89  
90  printk(KERN_ALERT "I was assigned major number %d. To talk to\n", Major);
91  printk(KERN_ALERT "the driver, create a dev file with\n");
92  printk(KERN_ALERT "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
93  
94  
95  /* Set up the FGPA irq line */
96  irq = gpio_to_irq(FPGA_IRQ_PIN);
97  
98  res = request_irq(irq, irq_handler, IRQF_DISABLED | IRQF_TRIGGER_RISING, "FPGA - IRQ", NULL); // IRQF_TRIGGER_FALLING
99       
100  ioaddress = ioremap(FPGA_BASE, 0x4000);
101       
102  return 0;
103}
104
105
106static void __exit qem_exit(void)
107{
108// int ret;
109  /*Tho order for free_irq, iounmap & unregister is very important */
110  free_irq(FPGA_IRQ_PIN, NULL);
111  iounmap(ioaddress);
112  unregister_chrdev(Major, DEVICE_NAME);
113  printk(KERN_INFO "FPGA driver is down...\n");
114}
115
116
117static int device_open(struct inode *inode, struct file *file)
118{
119  if (is_device_open)
120    return -EBUSY;
121
122  is_device_open = 1;
123
124  try_module_get(THIS_MODULE);
125
126  return SUCCESS;
127}
128
129static int device_release(struct inode *inode, struct file *file)
130{
131  is_device_open = 0;
132
133  module_put(THIS_MODULE);
134
135  return 0;
136}
137
138static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
139         char *buffer, /* buffer to fill with data */
140         size_t count, /* length of the buffer */
141         loff_t *offset)
142{
143
144  wait_event_interruptible(wq, interrupt_counter!=0);
145  return copy_to_user(buffer, &interrupt_counter, sizeof(interrupt_counter)) ? -EFAULT : 0;
146}
147
148static ssize_t
149device_write(struct file *filp, const char *buff, size_t count, loff_t * off)
150{
151  const char cmd = buff[0];
152  
153  if(cmd=='Q')
154  {
155    irq_enabled = 1;
156    printk(KERN_INFO "FPGA irq_enabled...\n");
157        
158  }
159  else
160    if(cmd=='S'){
161      irq_enabled = 0;
162      printk(KERN_INFO "FPGA irq disabled.\n");
163    }
164  
165  return 1;
166}
167
168module_init(qem_init);
169module_exit(qem_exit);
170
171
172MODULE_LICENSE("GPL");
173MODULE_AUTHOR("Andres Calderon <andresn@emqbit.com>");
174MODULE_DESCRIPTION("FPGA' IRQ driver");
175MODULE_VERSION("1:0.1");
176

Archive Download this file

Branches:
master



interactive