Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
| 1 | |
| 2 | #include <linux/types.h> |
| 3 | #include <linux/init.h> |
| 4 | #include <linux/input.h> |
| 5 | #include <linux/irq.h> |
| 6 | #include <linux/interrupt.h> |
| 7 | #include <linux/module.h> |
| 8 | #include <linux/gpio.h> |
| 9 | #include <asm/mach-jz4740/gpio.h> |
| 10 | |
| 11 | #define FPGA_IRQ_PIN JZ_GPIO_PORTC(15) |
| 12 | #define FPGA_CS JZ_GPIO_PORTB(26) |
| 13 | #define FPGA_BASE_BEGIN 0x15000000 |
| 14 | #define FPGA_BASE_END 0x17FFFFFF |
| 15 | |
| 16 | static unsigned int key_p; |
| 17 | static unsigned int key_e; |
| 18 | |
| 19 | /* |
| 20 | * Scancode to keycode tables. These are just the default setting, and |
| 21 | * are loadable via a userland utility. |
| 22 | */ |
| 23 | |
| 24 | #define ATKBD_KEYMAP_SIZE 512 |
| 25 | |
| 26 | static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = { |
| 27 | |
| 28 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES |
| 29 | //stream mode |
| 30 | iowrite32(0x000000EA,ioaddress); |
| 31 | mb(); |
| 32 | /* XXX: need a more general approach */ |
| 33 | |
| 34 | #include "hpps2atkbd.h" /* include the keyboard scancodes */ |
| 35 | |
| 36 | #else |
| 37 | 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117, |
| 38 | 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0, |
| 39 | 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183, |
| 40 | 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185, |
| 41 | 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0, |
| 42 | 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85, |
| 43 | 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0, |
| 44 | 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99, |
| 45 | |
| 46 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 47 | 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125, |
| 48 | 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127, |
| 49 | 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142, |
| 50 | 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0, |
| 51 | 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0, |
| 52 | 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112, |
| 53 | 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0, |
| 54 | |
| 55 | 0, 0, 0, 65, 99, |
| 56 | #endif |
| 57 | }; |
| 58 | |
| 59 | static struct input_dev *ps2kbd_dev; |
| 60 | static void __iomem *ioaddress; |
| 61 | |
| 62 | static irqreturn_t ps2_keyboard_interrupt(int irq, void *id) |
| 63 | { |
| 64 | unsigned char scancode, keycode; |
| 65 | |
| 66 | scancode = (unsigned char)(ioread32(ioaddress)& 0XFF); |
| 67 | rmb(); |
| 68 | |
| 69 | //printk(KERN_INFO "scancode %x\n", scancode); |
| 70 | |
| 71 | if (scancode == 0xAA)printk(KERN_INFO "PS/2 keyboard. ok\n"); |
| 72 | else if (scancode == 0xFC)printk(KERN_INFO "PS/2 keyboard. error\n"); |
| 73 | else if (scancode == 0xF0)key_p=0; |
| 74 | else if (scancode == 0xE0)key_e=1; |
| 75 | else if (scancode <= 0x7E){ /* scancodes < 0xf2 are keys */ |
| 76 | |
| 77 | keycode = atkbd_set2_keycode[scancode+0x80*key_e]; |
| 78 | |
| 79 | input_report_key(ps2kbd_dev, keycode, key_p); |
| 80 | input_sync(ps2kbd_dev); |
| 81 | key_p=1; |
| 82 | key_e=0; |
| 83 | } else /* scancodes >= 0xf2 are mouse data, most likely */ |
| 84 | printk(KERN_INFO "ps2kbd: unhandled scancode %x\n", scancode); |
| 85 | |
| 86 | return IRQ_HANDLED; |
| 87 | } |
| 88 | |
| 89 | static int __init ps2_keyboard_init(void) |
| 90 | { |
| 91 | |
| 92 | int i, error, res, irq; |
| 93 | |
| 94 | key_p=1; |
| 95 | key_e=0; |
| 96 | |
| 97 | ps2kbd_dev = input_allocate_device(); |
| 98 | if (!ps2kbd_dev) |
| 99 | return -ENOMEM; |
| 100 | |
| 101 | ps2kbd_dev->name = "PS2 Keyboard"; |
| 102 | ps2kbd_dev->phys = "ps2kbd/input0"; |
| 103 | ps2kbd_dev->id.bustype = BUS_HOST; |
| 104 | ps2kbd_dev->id.vendor = 0x0001; |
| 105 | ps2kbd_dev->id.product = 0x0001; |
| 106 | ps2kbd_dev->id.version = 0x0100; |
| 107 | |
| 108 | ps2kbd_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
| 109 | ps2kbd_dev->keycode = atkbd_set2_keycode; |
| 110 | ps2kbd_dev->keycodesize = sizeof(unsigned short); |
| 111 | ps2kbd_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); |
| 112 | |
| 113 | for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) { |
| 114 | set_bit(atkbd_set2_keycode[i], ps2kbd_dev->keybit); |
| 115 | } |
| 116 | |
| 117 | /* error check */ |
| 118 | error = input_register_device(ps2kbd_dev); |
| 119 | if (error) { |
| 120 | input_free_device(ps2kbd_dev); |
| 121 | return error; |
| 122 | } |
| 123 | |
| 124 | /* Set up the FGPA irq line */ |
| 125 | irq = gpio_to_irq(FPGA_IRQ_PIN); |
| 126 | res = request_irq(irq, ps2_keyboard_interrupt, IRQF_DISABLED | IRQF_TRIGGER_RISING, "FPGA - IRQ", NULL); // IRQF_TRIGGER_FALLING |
| 127 | |
| 128 | /* Set GPIOB26 as part of External Memory Controller*/ |
| 129 | jz_gpio_set_function (FPGA_CS, JZ_GPIO_FUNC_NONE); |
| 130 | /* Use ioremap to get a handle on our region */ |
| 131 | ioaddress = __ioremap(FPGA_BASE_BEGIN, FPGA_BASE_END - FPGA_BASE_BEGIN, _CACHE_UNCACHED); |
| 132 | |
| 133 | return 0; |
| 134 | } |
| 135 | |
| 136 | static void __exit ps2_keyboard_exit(void) |
| 137 | { |
| 138 | free_irq(FPGA_IRQ_PIN, NULL); |
| 139 | __iounmap(ioaddress); |
| 140 | input_unregister_device(ps2kbd_dev); |
| 141 | } |
| 142 | |
| 143 | module_init(ps2_keyboard_init); |
| 144 | module_exit(ps2_keyboard_exit); |
| 145 | |
| 146 | MODULE_AUTHOR("Ari Bejarano <aabejaranoh@unal.edu.co>"); |
| 147 | MODULE_DESCRIPTION("PS/2 Keyboard Driver"); |
| 148 | MODULE_LICENSE("GPL v2"); |
| 149 | MODULE_ALIAS("platform:ps2-keyboard"); |
| 150 |
Branches:
master
