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>
17 #include <linux/slab.h>
19 struct opencores_kbd
{
20 struct input_dev
*input
;
21 struct resource
*addr_res
;
24 unsigned short keycodes
[128];
27 static irqreturn_t
opencores_kbd_isr(int irq
, void *dev_id
)
29 struct opencores_kbd
*opencores_kbd
= dev_id
;
30 struct input_dev
*input
= opencores_kbd
->input
;
33 c
= readb(opencores_kbd
->addr
);
34 input_report_key(input
, c
& 0x7f, c
& 0x80 ? 0 : 1);
40 static int opencores_kbd_probe(struct platform_device
*pdev
)
42 struct input_dev
*input
;
43 struct opencores_kbd
*opencores_kbd
;
47 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
49 dev_err(&pdev
->dev
, "missing board memory resource\n");
53 irq
= platform_get_irq(pdev
, 0);
55 dev_err(&pdev
->dev
, "missing board IRQ resource\n");
59 opencores_kbd
= kzalloc(sizeof(*opencores_kbd
), GFP_KERNEL
);
60 input
= input_allocate_device();
61 if (!opencores_kbd
|| !input
) {
62 dev_err(&pdev
->dev
, "failed to allocate device structures\n");
67 opencores_kbd
->addr_res
= res
;
68 res
= request_mem_region(res
->start
, resource_size(res
), pdev
->name
);
70 dev_err(&pdev
->dev
, "failed to request I/O memory\n");
75 opencores_kbd
->addr
= ioremap(res
->start
, resource_size(res
));
76 if (!opencores_kbd
->addr
) {
77 dev_err(&pdev
->dev
, "failed to remap I/O memory\n");
82 opencores_kbd
->input
= input
;
83 opencores_kbd
->irq
= irq
;
85 input
->name
= pdev
->name
;
86 input
->phys
= "opencores-kbd/input0";
87 input
->dev
.parent
= &pdev
->dev
;
89 input_set_drvdata(input
, opencores_kbd
);
91 input
->id
.bustype
= BUS_HOST
;
92 input
->id
.vendor
= 0x0001;
93 input
->id
.product
= 0x0001;
94 input
->id
.version
= 0x0100;
96 input
->keycode
= opencores_kbd
->keycodes
;
97 input
->keycodesize
= sizeof(opencores_kbd
->keycodes
[0]);
98 input
->keycodemax
= ARRAY_SIZE(opencores_kbd
->keycodes
);
100 __set_bit(EV_KEY
, input
->evbit
);
102 for (i
= 0; i
< ARRAY_SIZE(opencores_kbd
->keycodes
); i
++) {
104 * OpenCores controller happens to have scancodes match
105 * our KEY_* definitions.
107 opencores_kbd
->keycodes
[i
] = i
;
108 __set_bit(opencores_kbd
->keycodes
[i
], input
->keybit
);
110 __clear_bit(KEY_RESERVED
, input
->keybit
);
112 error
= request_irq(irq
, &opencores_kbd_isr
,
113 IRQF_TRIGGER_RISING
, pdev
->name
, opencores_kbd
);
115 dev_err(&pdev
->dev
, "unable to claim irq %d\n", irq
);
119 error
= input_register_device(input
);
121 dev_err(&pdev
->dev
, "unable to register input device\n");
125 platform_set_drvdata(pdev
, opencores_kbd
);
130 free_irq(irq
, opencores_kbd
);
132 iounmap(opencores_kbd
->addr
);
134 release_mem_region(res
->start
, resource_size(res
));
136 input_free_device(input
);
137 kfree(opencores_kbd
);
142 static int opencores_kbd_remove(struct platform_device
*pdev
)
144 struct opencores_kbd
*opencores_kbd
= platform_get_drvdata(pdev
);
146 free_irq(opencores_kbd
->irq
, opencores_kbd
);
148 iounmap(opencores_kbd
->addr
);
149 release_mem_region(opencores_kbd
->addr_res
->start
,
150 resource_size(opencores_kbd
->addr_res
));
151 input_unregister_device(opencores_kbd
->input
);
152 kfree(opencores_kbd
);
157 static struct platform_driver opencores_kbd_device_driver
= {
158 .probe
= opencores_kbd_probe
,
159 .remove
= opencores_kbd_remove
,
161 .name
= "opencores-kbd",
164 module_platform_driver(opencores_kbd_device_driver
);
166 MODULE_LICENSE("GPL");
167 MODULE_AUTHOR("Javier Herrero <jherrero@hvsistemas.es>");
168 MODULE_DESCRIPTION("Keyboard driver for OpenCores Keyboard Controller");