2 * linux/drivers/input/keyboard/pxa27x_keyboard.c
4 * Driver for the pxa27x matrix keyboard controller.
6 * Created: Feb 22, 2007
7 * Author: Rodolfo Giometti <giometti@linux.it>
9 * Based on a previous implementations by Kevin O'Connor
10 * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
11 * on some suggestions by Nicolas Pitre <nico@cam.org>.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/interrupt.h>
23 #include <linux/input.h>
24 #include <linux/device.h>
25 #include <linux/platform_device.h>
27 #include <asm/mach-types.h>
28 #include <asm/mach/arch.h>
29 #include <asm/mach/map.h>
31 #include <asm/arch/hardware.h>
32 #include <asm/arch/pxa-regs.h>
33 #include <asm/arch/irqs.h>
34 #include <asm/arch/pxa27x_keyboard.h>
36 #define DRIVER_NAME "pxa27x-keyboard"
38 #define KPASMKP(col) (col/2 == 0 ? KPASMKP0 : \
39 col/2 == 1 ? KPASMKP1 : \
40 col/2 == 2 ? KPASMKP2 : KPASMKP3)
41 #define KPASMKPx_MKC(row, col) (1 << (row + 16 * (col % 2)))
43 static irqreturn_t
pxakbd_irq_handler(int irq
, void *dev_id
)
45 struct platform_device
*pdev
= dev_id
;
46 struct pxa27x_keyboard_platform_data
*pdata
= pdev
->dev
.platform_data
;
47 struct input_dev
*input_dev
= platform_get_drvdata(pdev
);
48 unsigned long kpc
= KPC
;
52 unsigned long kpdk
= KPDK
;
54 if (!(kpdk
& KPDK_DKP
)) {
55 /* better luck next time */
56 } else if (kpc
& KPC_REE0
) {
57 unsigned long kprec
= KPREC
;
60 if (kprec
& KPREC_OF0
)
61 rel
= (kprec
& 0xff) + 0x7f;
62 else if (kprec
& KPREC_UF0
)
63 rel
= (kprec
& 0xff) - 0x7f - 0xff;
65 rel
= (kprec
& 0xff) - 0x7f;
68 input_report_rel(input_dev
, REL_WHEEL
, rel
);
69 input_sync(input_dev
);
75 /* report the status of every button */
76 for (row
= 0; row
< pdata
->nr_rows
; row
++) {
77 for (col
= 0; col
< pdata
->nr_cols
; col
++) {
78 p
= KPASMKP(col
) & KPASMKPx_MKC(row
, col
) ?
80 pr_debug("keycode %x - pressed %x\n",
81 pdata
->keycodes
[row
][col
], p
);
82 input_report_key(input_dev
,
83 pdata
->keycodes
[row
][col
], p
);
86 input_sync(input_dev
);
92 static int pxakbd_open(struct input_dev
*dev
)
94 /* Set keypad control register */
97 (2 << 6) | KPC_REE0
| KPC_DK_DEB_SEL
|
98 KPC_ME
| KPC_MIE
| KPC_DE
| KPC_DIE
);
100 KPC
&= ~KPC_AS
; /* disable automatic scan */
101 KPC
&= ~KPC_IMKP
; /* do not ignore multiple keypresses */
103 /* Set rotary count to mid-point value */
106 /* Enable unit clock */
107 pxa_set_cken(CKEN19_KEYPAD
, 1);
112 static void pxakbd_close(struct input_dev
*dev
)
114 /* Disable clock unit */
115 pxa_set_cken(CKEN19_KEYPAD
, 0);
119 static int pxakbd_suspend(struct platform_device
*pdev
, pm_message_t state
)
121 struct pxa27x_keyboard_platform_data
*pdata
= pdev
->dev
.platform_data
;
123 /* Save controller status */
124 pdata
->reg_kpc
= KPC
;
125 pdata
->reg_kprec
= KPREC
;
130 static int pxakbd_resume(struct platform_device
*pdev
)
132 struct pxa27x_keyboard_platform_data
*pdata
= pdev
->dev
.platform_data
;
133 struct input_dev
*input_dev
= platform_get_drvdata(pdev
);
135 mutex_lock(&input_dev
->mutex
);
137 if (input_dev
->users
) {
138 /* Restore controller status */
139 KPC
= pdata
->reg_kpc
;
140 KPREC
= pdata
->reg_kprec
;
142 /* Enable unit clock */
143 pxa_set_cken(CKEN19_KEYPAD
, 1);
146 mutex_unlock(&input_dev
->mutex
);
151 #define pxakbd_suspend NULL
152 #define pxakbd_resume NULL
155 static int __devinit
pxakbd_probe(struct platform_device
*pdev
)
157 struct pxa27x_keyboard_platform_data
*pdata
= pdev
->dev
.platform_data
;
158 struct input_dev
*input_dev
;
159 int i
, row
, col
, error
;
161 /* Create and register the input driver. */
162 input_dev
= input_allocate_device();
164 printk(KERN_ERR
"Cannot request keypad device\n");
168 input_dev
->name
= DRIVER_NAME
;
169 input_dev
->id
.bustype
= BUS_HOST
;
170 input_dev
->open
= pxakbd_open
;
171 input_dev
->close
= pxakbd_close
;
172 input_dev
->dev
.parent
= &pdev
->dev
;
174 input_dev
->evbit
[0] = BIT(EV_KEY
) | BIT(EV_REP
) | BIT(EV_REL
);
175 input_dev
->relbit
[LONG(REL_WHEEL
)] = BIT(REL_WHEEL
);
176 for (row
= 0; row
< pdata
->nr_rows
; row
++) {
177 for (col
= 0; col
< pdata
->nr_cols
; col
++) {
178 int code
= pdata
->keycodes
[row
][col
];
180 set_bit(code
, input_dev
->keybit
);
184 error
= request_irq(IRQ_KEYPAD
, pxakbd_irq_handler
, IRQF_DISABLED
,
187 printk(KERN_ERR
"Cannot request keypad IRQ\n");
188 pxa_set_cken(CKEN19_KEYPAD
, 0);
192 platform_set_drvdata(pdev
, input_dev
);
194 /* Register the input device */
195 error
= input_register_device(input_dev
);
200 for (i
= 0; i
< pdata
->nr_rows
+ pdata
->nr_cols
; i
++)
201 pxa_gpio_mode(pdata
->gpio_modes
[i
]);
204 * Store rows/cols info into keyboard registers.
207 KPC
|= (pdata
->nr_rows
- 1) << 26;
208 KPC
|= (pdata
->nr_cols
- 1) << 23;
210 for (col
= 0; col
< pdata
->nr_cols
; col
++)
211 KPC
|= KPC_MS0
<< col
;
216 platform_set_drvdata(pdev
, NULL
);
217 free_irq(IRQ_KEYPAD
, pdev
);
219 input_free_device(input_dev
);
223 static int __devexit
pxakbd_remove(struct platform_device
*pdev
)
225 struct input_dev
*input_dev
= platform_get_drvdata(pdev
);
227 input_unregister_device(input_dev
);
228 free_irq(IRQ_KEYPAD
, pdev
);
229 platform_set_drvdata(pdev
, NULL
);
234 static struct platform_driver pxakbd_driver
= {
235 .probe
= pxakbd_probe
,
236 .remove
= __devexit_p(pxakbd_remove
),
237 .suspend
= pxakbd_suspend
,
238 .resume
= pxakbd_resume
,
244 static int __init
pxakbd_init(void)
246 return platform_driver_register(&pxakbd_driver
);
249 static void __exit
pxakbd_exit(void)
251 platform_driver_unregister(&pxakbd_driver
);
254 module_init(pxakbd_init
);
255 module_exit(pxakbd_exit
);
257 MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver");
258 MODULE_LICENSE("GPL");