nn-usb-fpga/PS2_INTERFACE/drivers/kbps2.c

163 lines
4.4 KiB
C
Executable File

/*
* Driver preliminar y de pruebas de teclado ps2 kbps2
*
* Author: Ari Andrés Bejarano H.
*
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO, printk() */
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/interrupt.h> /* We want an interrupt */
#include <linux/irq.h> /* We want an interrupt */
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h> /*ioremap ioremap_nocache iounmap iowriteXX ioreadXX*/
#include <linux/gpio.h>
#include <asm/mach-jz4740/gpio.h>
#include<asm/system.h> /*rmb*/
#define FPGA_IRQ_PIN JZ_GPIO_PORTC(15)
#define FPGA_CS JZ_GPIO_PORTB(26)
#define FPGA_BASE_BEGIN 0x15000000
#define FPGA_BASE_END 0x17FFFFFF
#define SUCCESS 0
#define DEVICE_NAME "kbps2" /* Dev name as it appears in /proc/devices */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ari");
MODULE_DESCRIPTION("Keyboard ps2");
MODULE_VERSION("1.0");
/* Declaration of kbps2.c functions */
static irqreturn_t irq_handler(int irq, void *dev_id);
static int kbps2_open(struct inode *, struct file *);
static int kbps2_release(struct inode *, struct file *);
static ssize_t kbps2_read(struct file *, char *, size_t, loff_t *);
static ssize_t kbps2_write(struct file *, const char *, size_t, loff_t *);
static int __init kbps2_init(void);
static void __exit kbps2_exit(void);
/* Structure that declares the usual file */
/* access functions */
struct file_operations fops = {
.owner = THIS_MODULE,
.read = kbps2_read,
.write = kbps2_write,
.open = kbps2_open,
.release = kbps2_release
};
/* Declaration of the init and exit functions */
module_init(kbps2_init);
module_exit(kbps2_exit);
/* Global variables of the driver */
static int irq_enabled = 0;
static int is_device_open = 0; /* Is device open? Used to prevent multiple access to device */
static int Major=65; /* Major number */
static DECLARE_WAIT_QUEUE_HEAD(wq);
static void __iomem *ioaddress;
static unsigned int interrupt_counter = 0;
static int __init kbps2_init(void)
{
int res, irq, result;
barrier();
printk(KERN_INFO "FPGA module is Up.\n");
interrupt_counter = 0;
/* Registering device */
result = register_chrdev(Major, DEVICE_NAME, &fops);
if (result < 0) {
printk("<1>memory: cannot obtain major number %d\n", Major);
return result;
}
/* Set up the FGPA irq line */
irq = gpio_to_irq(FPGA_IRQ_PIN);
res = request_irq(irq, irq_handler, IRQF_DISABLED | IRQF_TRIGGER_RISING, "FPGA - IRQ", NULL); // IRQF_TRIGGER_FALLING
irq_enabled = 1;
printk(KERN_INFO "FPGA irq_enabled...\n");
/* Set GPIOB26 as part of External Memory Controller*/
jz_gpio_set_function (FPGA_CS, JZ_GPIO_FUNC_NONE);
/* Use ioremap to get a handle on our region */
ioaddress = __ioremap(FPGA_BASE_BEGIN, FPGA_BASE_END - FPGA_BASE_BEGIN, _CACHE_UNCACHED);
return 0;
}
static void __exit kbps2_exit(void)
{
// int ret;
/*Tho order for free_irq, iounmap & unregister is very important */
free_irq(FPGA_IRQ_PIN, NULL);
__iounmap(ioaddress);
unregister_chrdev(Major, DEVICE_NAME);
printk(KERN_INFO "FPGA driver is down...\n");
}
static irqreturn_t irq_handler(int irq, void *dev_id)
{
unsigned int red;
if(irq_enabled)
{
interrupt_counter++;
printk(KERN_INFO "interrupt_counter=%d\n",interrupt_counter);
red=ioread32(ioaddress)& 0XFF;
rmb();
printk("%X \n", red);
wake_up_interruptible(&wq);
}
return IRQ_HANDLED;
}
static int kbps2_open(struct inode *inode, struct file *file)
{
if (is_device_open)
return -EBUSY;
is_device_open = 1;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int kbps2_release(struct inode *inode, struct file *file)
{
is_device_open = 0;
module_put(THIS_MODULE);
return 0;
}
static ssize_t kbps2_read(struct file *filp, char *buffer, size_t count, loff_t *offset)
{
unsigned int red;
printk(KERN_INFO "read______-_-\n");
red=ioread32(ioaddress)& 0XFF;
rmb();
printk("%X\n", red);
return 0;
}
static ssize_t kbps2_write(struct file *filp, const char *buff, size_t count, loff_t * off)
{
printk(KERN_INFO "write______-_-\n");
printk("%X\n", buff[0]);
iowrite32(buff[0],ioaddress);
wmb();
return 1;
}