/* * Driver preliminar y de pruebas de teclado ps2 kbps2 * * Author: Ari Andrés Bejarano H. * */ #include /* Needed by all modules */ #include /* Needed for KERN_INFO, printk() */ #include #include #include /* We want an interrupt */ #include /* We want an interrupt */ #include #include #include #include /*ioremap ioremap_nocache iounmap iowriteXX ioreadXX*/ #include #include #include /*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; }