2 * SPEAr Keyboard Driver
3 * Based on omap-keypad driver
5 * Copyright (C) 2010 ST Microelectronics
6 * Rajeev Kumar<rajeev-dlh.kumar@st.com>
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
13 #include <linux/clk.h>
14 #include <linux/errno.h>
15 #include <linux/init.h>
16 #include <linux/interrupt.h>
17 #include <linux/input.h>
19 #include <linux/irq.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/pm_wakeup.h>
24 #include <linux/slab.h>
25 #include <linux/types.h>
26 #include <plat/keyboard.h>
28 /* Keyboard Registers */
29 #define MODE_REG 0x00 /* 16 bit reg */
30 #define STATUS_REG 0x0C /* 2 bit reg */
31 #define DATA_REG 0x10 /* 8 bit reg */
32 #define INTR_MASK 0x54
36 * pclk freq mask = (APB FEQ -1)= 82 MHZ.Programme bit 15-9 in mode
37 * control register as 1010010(82MHZ)
39 #define PCLK_FREQ_MSK 0xA400 /* 82 MHz */
40 #define START_SCAN 0x0100
41 #define SCAN_RATE_10 0x0000
42 #define SCAN_RATE_20 0x0004
43 #define SCAN_RATE_40 0x0008
44 #define SCAN_RATE_80 0x000C
45 #define MODE_KEYBOARD 0x0002
46 #define DATA_AVAIL 0x2
48 #define KEY_MASK 0xFF000000
49 #define KEY_VALUE 0x00FFFFFF
51 #define COLUMN_MASK 0x0F
55 struct input_dev
*input
;
57 void __iomem
*io_base
;
60 unsigned short last_key
;
61 unsigned short keycodes
[256];
64 static irqreturn_t
spear_kbd_interrupt(int irq
, void *dev_id
)
66 struct spear_kbd
*kbd
= dev_id
;
67 struct input_dev
*input
= kbd
->input
;
71 sts
= readb(kbd
->io_base
+ STATUS_REG
);
72 if (!(sts
& DATA_AVAIL
))
75 if (kbd
->last_key
!= KEY_RESERVED
) {
76 input_report_key(input
, kbd
->last_key
, 0);
77 kbd
->last_key
= KEY_RESERVED
;
80 /* following reads active (row, col) pair */
81 val
= readb(kbd
->io_base
+ DATA_REG
);
82 key
= kbd
->keycodes
[val
];
84 input_event(input
, EV_MSC
, MSC_SCAN
, val
);
85 input_report_key(input
, key
, 1);
91 writeb(0, kbd
->io_base
+ STATUS_REG
);
96 static int spear_kbd_open(struct input_dev
*dev
)
98 struct spear_kbd
*kbd
= input_get_drvdata(dev
);
102 kbd
->last_key
= KEY_RESERVED
;
104 error
= clk_enable(kbd
->clk
);
108 /* program keyboard */
109 val
= SCAN_RATE_80
| MODE_KEYBOARD
| PCLK_FREQ_MSK
;
110 writew(val
, kbd
->io_base
+ MODE_REG
);
111 writeb(1, kbd
->io_base
+ STATUS_REG
);
114 val
= readw(kbd
->io_base
+ MODE_REG
);
116 writew(val
, kbd
->io_base
+ MODE_REG
);
121 static void spear_kbd_close(struct input_dev
*dev
)
123 struct spear_kbd
*kbd
= input_get_drvdata(dev
);
127 val
= readw(kbd
->io_base
+ MODE_REG
);
129 writew(val
, kbd
->io_base
+ MODE_REG
);
131 clk_disable(kbd
->clk
);
133 kbd
->last_key
= KEY_RESERVED
;
136 static int __devinit
spear_kbd_probe(struct platform_device
*pdev
)
138 const struct kbd_platform_data
*pdata
= pdev
->dev
.platform_data
;
139 const struct matrix_keymap_data
*keymap
;
140 struct spear_kbd
*kbd
;
141 struct input_dev
*input_dev
;
142 struct resource
*res
;
147 dev_err(&pdev
->dev
, "Invalid platform data\n");
151 keymap
= pdata
->keymap
;
153 dev_err(&pdev
->dev
, "no keymap defined\n");
157 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
159 dev_err(&pdev
->dev
, "no keyboard resource defined\n");
163 irq
= platform_get_irq(pdev
, 0);
165 dev_err(&pdev
->dev
, "not able to get irq for the device\n");
169 kbd
= kzalloc(sizeof(*kbd
), GFP_KERNEL
);
170 input_dev
= input_allocate_device();
171 if (!kbd
|| !input_dev
) {
172 dev_err(&pdev
->dev
, "out of memory\n");
177 kbd
->input
= input_dev
;
179 kbd
->res
= request_mem_region(res
->start
, resource_size(res
),
182 dev_err(&pdev
->dev
, "keyboard region already claimed\n");
187 kbd
->io_base
= ioremap(res
->start
, resource_size(res
));
189 dev_err(&pdev
->dev
, "ioremap failed for kbd_region\n");
191 goto err_release_mem_region
;
194 kbd
->clk
= clk_get(&pdev
->dev
, NULL
);
195 if (IS_ERR(kbd
->clk
)) {
196 error
= PTR_ERR(kbd
->clk
);
200 input_dev
->name
= "Spear Keyboard";
201 input_dev
->phys
= "keyboard/input0";
202 input_dev
->dev
.parent
= &pdev
->dev
;
203 input_dev
->id
.bustype
= BUS_HOST
;
204 input_dev
->id
.vendor
= 0x0001;
205 input_dev
->id
.product
= 0x0001;
206 input_dev
->id
.version
= 0x0100;
207 input_dev
->open
= spear_kbd_open
;
208 input_dev
->close
= spear_kbd_close
;
210 __set_bit(EV_KEY
, input_dev
->evbit
);
212 __set_bit(EV_REP
, input_dev
->evbit
);
213 input_set_capability(input_dev
, EV_MSC
, MSC_SCAN
);
215 input_dev
->keycode
= kbd
->keycodes
;
216 input_dev
->keycodesize
= sizeof(kbd
->keycodes
[0]);
217 input_dev
->keycodemax
= ARRAY_SIZE(kbd
->keycodes
);
219 matrix_keypad_build_keymap(keymap
, ROW_SHIFT
,
220 input_dev
->keycode
, input_dev
->keybit
);
222 input_set_drvdata(input_dev
, kbd
);
224 error
= request_irq(irq
, spear_kbd_interrupt
, 0, "keyboard", kbd
);
226 dev_err(&pdev
->dev
, "request_irq fail\n");
230 error
= input_register_device(input_dev
);
232 dev_err(&pdev
->dev
, "Unable to register keyboard device\n");
236 device_init_wakeup(&pdev
->dev
, 1);
237 platform_set_drvdata(pdev
, kbd
);
242 free_irq(kbd
->irq
, kbd
);
246 iounmap(kbd
->io_base
);
247 err_release_mem_region
:
248 release_mem_region(res
->start
, resource_size(res
));
250 input_free_device(input_dev
);
256 static int __devexit
spear_kbd_remove(struct platform_device
*pdev
)
258 struct spear_kbd
*kbd
= platform_get_drvdata(pdev
);
260 free_irq(kbd
->irq
, kbd
);
261 input_unregister_device(kbd
->input
);
263 iounmap(kbd
->io_base
);
264 release_mem_region(kbd
->res
->start
, resource_size(kbd
->res
));
267 device_init_wakeup(&pdev
->dev
, 1);
268 platform_set_drvdata(pdev
, NULL
);
274 static int spear_kbd_suspend(struct device
*dev
)
276 struct platform_device
*pdev
= to_platform_device(dev
);
277 struct spear_kbd
*kbd
= platform_get_drvdata(pdev
);
278 struct input_dev
*input_dev
= kbd
->input
;
280 mutex_lock(&input_dev
->mutex
);
282 if (input_dev
->users
)
283 clk_enable(kbd
->clk
);
285 if (device_may_wakeup(&pdev
->dev
))
286 enable_irq_wake(kbd
->irq
);
288 mutex_unlock(&input_dev
->mutex
);
293 static int spear_kbd_resume(struct device
*dev
)
295 struct platform_device
*pdev
= to_platform_device(dev
);
296 struct spear_kbd
*kbd
= platform_get_drvdata(pdev
);
297 struct input_dev
*input_dev
= kbd
->input
;
299 mutex_lock(&input_dev
->mutex
);
301 if (device_may_wakeup(&pdev
->dev
))
302 disable_irq_wake(kbd
->irq
);
304 if (input_dev
->users
)
305 clk_enable(kbd
->clk
);
307 mutex_unlock(&input_dev
->mutex
);
312 static const struct dev_pm_ops spear_kbd_pm_ops
= {
313 .suspend
= spear_kbd_suspend
,
314 .resume
= spear_kbd_resume
,
318 static struct platform_driver spear_kbd_driver
= {
319 .probe
= spear_kbd_probe
,
320 .remove
= __devexit_p(spear_kbd_remove
),
323 .owner
= THIS_MODULE
,
325 .pm
= &spear_kbd_pm_ops
,
330 static int __init
spear_kbd_init(void)
332 return platform_driver_register(&spear_kbd_driver
);
334 module_init(spear_kbd_init
);
336 static void __exit
spear_kbd_exit(void)
338 platform_driver_unregister(&spear_kbd_driver
);
340 module_exit(spear_kbd_exit
);
342 MODULE_AUTHOR("Rajeev Kumar");
343 MODULE_DESCRIPTION("SPEAr Keyboard Driver");
344 MODULE_LICENSE("GPL");