2 * OpenCores Keyboard Controller Driver
3 * http://www.opencores.org/project,keyboardcontroller
5 * Copyright 2007-2009 HV Sistemas S.L.
7 * Licensed under the GPL-2 or later.
10 #include <linux/input.h>
11 #include <linux/interrupt.h>
13 #include <linux/ioport.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
18 struct opencores_kbd
{
19 struct input_dev
*input
;
20 struct resource
*addr_res
;
23 unsigned short keycodes
[128];
26 static irqreturn_t
opencores_kbd_isr(int irq
, void *dev_id
)
28 struct opencores_kbd
*opencores_kbd
= dev_id
;
29 struct input_dev
*input
= opencores_kbd
->input
;
32 c
= readb(opencores_kbd
->addr
);
33 input_report_key(input
, c
& 0x7f, c
& 0x80 ? 0 : 1);
39 static int __devinit
opencores_kbd_probe(struct platform_device
*pdev
)
41 struct input_dev
*input
;
42 struct opencores_kbd
*opencores_kbd
;
46 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
48 dev_err(&pdev
->dev
, "missing board memory resource\n");
52 irq
= platform_get_irq(pdev
, 0);
54 dev_err(&pdev
->dev
, "missing board IRQ resource\n");
58 opencores_kbd
= kzalloc(sizeof(*opencores_kbd
), GFP_KERNEL
);
59 input
= input_allocate_device();
60 if (!opencores_kbd
|| !input
) {
61 dev_err(&pdev
->dev
, "failed to allocate device structures\n");
66 opencores_kbd
->addr_res
= res
;
67 res
= request_mem_region(res
->start
, resource_size(res
), pdev
->name
);
69 dev_err(&pdev
->dev
, "failed to request I/O memory\n");
74 opencores_kbd
->addr
= ioremap(res
->start
, resource_size(res
));
75 if (!opencores_kbd
->addr
) {
76 dev_err(&pdev
->dev
, "failed to remap I/O memory\n");
81 opencores_kbd
->input
= input
;
82 opencores_kbd
->irq
= irq
;
84 input
->name
= pdev
->name
;
85 input
->phys
= "opencores-kbd/input0";
86 input
->dev
.parent
= &pdev
->dev
;
88 input_set_drvdata(input
, opencores_kbd
);
90 input
->id
.bustype
= BUS_HOST
;
91 input
->id
.vendor
= 0x0001;
92 input
->id
.product
= 0x0001;
93 input
->id
.version
= 0x0100;
95 input
->keycode
= opencores_kbd
->keycodes
;
96 input
->keycodesize
= sizeof(opencores_kbd
->keycodes
[0]);
97 input
->keycodemax
= ARRAY_SIZE(opencores_kbd
->keycodes
);
99 __set_bit(EV_KEY
, input
->evbit
);
101 for (i
= 0; i
< ARRAY_SIZE(opencores_kbd
->keycodes
); i
++) {
103 * OpenCores controller happens to have scancodes match
104 * our KEY_* definitions.
106 opencores_kbd
->keycodes
[i
] = i
;
107 __set_bit(opencores_kbd
->keycodes
[i
], input
->keybit
);
109 __clear_bit(KEY_RESERVED
, input
->keybit
);
111 error
= request_irq(irq
, &opencores_kbd_isr
,
112 IRQF_TRIGGER_RISING
, pdev
->name
, opencores_kbd
);
114 dev_err(&pdev
->dev
, "unable to claim irq %d\n", irq
);
118 error
= input_register_device(input
);
120 dev_err(&pdev
->dev
, "unable to register input device\n");
124 platform_set_drvdata(pdev
, opencores_kbd
);
129 free_irq(irq
, opencores_kbd
);
131 iounmap(opencores_kbd
->addr
);
133 release_mem_region(res
->start
, resource_size(res
));
135 input_free_device(input
);
136 kfree(opencores_kbd
);
141 static int __devexit
opencores_kbd_remove(struct platform_device
*pdev
)
143 struct opencores_kbd
*opencores_kbd
= platform_get_drvdata(pdev
);
145 free_irq(opencores_kbd
->irq
, opencores_kbd
);
147 iounmap(opencores_kbd
->addr
);
148 release_mem_region(opencores_kbd
->addr_res
->start
,
149 resource_size(opencores_kbd
->addr_res
));
150 input_unregister_device(opencores_kbd
->input
);
151 kfree(opencores_kbd
);
153 platform_set_drvdata(pdev
, NULL
);
158 static struct platform_driver opencores_kbd_device_driver
= {
159 .probe
= opencores_kbd_probe
,
160 .remove
= __devexit_p(opencores_kbd_remove
),
162 .name
= "opencores-kbd",
166 static int __init
opencores_kbd_init(void)
168 return platform_driver_register(&opencores_kbd_device_driver
);
170 module_init(opencores_kbd_init
);
172 static void __exit
opencores_kbd_exit(void)
174 platform_driver_unregister(&opencores_kbd_device_driver
);
176 module_exit(opencores_kbd_exit
);
178 MODULE_LICENSE("GPL");
179 MODULE_AUTHOR("Javier Herrero <jherrero@hvsistemas.es>");
180 MODULE_DESCRIPTION("Keyboard driver for OpenCores Keyboard Controller");