2 * Samsung keypad driver
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 * Author: Donghwa Lee <dh09.lee@samsung.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
14 #include <linux/clk.h>
15 #include <linux/delay.h>
16 #include <linux/err.h>
17 #include <linux/init.h>
18 #include <linux/input.h>
19 #include <linux/interrupt.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/slab.h>
25 #include <linux/of_gpio.h>
26 #include <linux/sched.h>
27 #include <plat/keypad.h>
29 #define SAMSUNG_KEYIFCON 0x00
30 #define SAMSUNG_KEYIFSTSCLR 0x04
31 #define SAMSUNG_KEYIFCOL 0x08
32 #define SAMSUNG_KEYIFROW 0x0c
33 #define SAMSUNG_KEYIFFC 0x10
35 /* SAMSUNG_KEYIFCON */
36 #define SAMSUNG_KEYIFCON_INT_F_EN (1 << 0)
37 #define SAMSUNG_KEYIFCON_INT_R_EN (1 << 1)
38 #define SAMSUNG_KEYIFCON_DF_EN (1 << 2)
39 #define SAMSUNG_KEYIFCON_FC_EN (1 << 3)
40 #define SAMSUNG_KEYIFCON_WAKEUPEN (1 << 4)
42 /* SAMSUNG_KEYIFSTSCLR */
43 #define SAMSUNG_KEYIFSTSCLR_P_INT_MASK (0xff << 0)
44 #define SAMSUNG_KEYIFSTSCLR_R_INT_MASK (0xff << 8)
45 #define SAMSUNG_KEYIFSTSCLR_R_INT_OFFSET 8
46 #define S5PV210_KEYIFSTSCLR_P_INT_MASK (0x3fff << 0)
47 #define S5PV210_KEYIFSTSCLR_R_INT_MASK (0x3fff << 16)
48 #define S5PV210_KEYIFSTSCLR_R_INT_OFFSET 16
50 /* SAMSUNG_KEYIFCOL */
51 #define SAMSUNG_KEYIFCOL_MASK (0xff << 0)
52 #define S5PV210_KEYIFCOLEN_MASK (0xff << 8)
54 /* SAMSUNG_KEYIFROW */
55 #define SAMSUNG_KEYIFROW_MASK (0xff << 0)
56 #define S5PV210_KEYIFROW_MASK (0x3fff << 0)
59 #define SAMSUNG_KEYIFFC_MASK (0x3ff << 0)
61 enum samsung_keypad_type
{
66 struct samsung_keypad
{
67 struct input_dev
*input_dev
;
70 wait_queue_head_t wait
;
73 enum samsung_keypad_type type
;
74 unsigned int row_shift
;
77 unsigned int row_state
[SAMSUNG_MAX_COLS
];
79 int row_gpios
[SAMSUNG_MAX_ROWS
];
80 int col_gpios
[SAMSUNG_MAX_COLS
];
82 unsigned short keycodes
[];
85 static void samsung_keypad_scan(struct samsung_keypad
*keypad
,
86 unsigned int *row_state
)
91 for (col
= 0; col
< keypad
->cols
; col
++) {
92 if (keypad
->type
== KEYPAD_TYPE_S5PV210
) {
93 val
= S5PV210_KEYIFCOLEN_MASK
;
94 val
&= ~(1 << col
) << 8;
96 val
= SAMSUNG_KEYIFCOL_MASK
;
100 writel(val
, keypad
->base
+ SAMSUNG_KEYIFCOL
);
103 val
= readl(keypad
->base
+ SAMSUNG_KEYIFROW
);
104 row_state
[col
] = ~val
& ((1 << keypad
->rows
) - 1);
107 /* KEYIFCOL reg clear */
108 writel(0, keypad
->base
+ SAMSUNG_KEYIFCOL
);
111 static bool samsung_keypad_report(struct samsung_keypad
*keypad
,
112 unsigned int *row_state
)
114 struct input_dev
*input_dev
= keypad
->input_dev
;
115 unsigned int changed
;
116 unsigned int pressed
;
117 unsigned int key_down
= 0;
119 unsigned int col
, row
;
121 for (col
= 0; col
< keypad
->cols
; col
++) {
122 changed
= row_state
[col
] ^ keypad
->row_state
[col
];
123 key_down
|= row_state
[col
];
127 for (row
= 0; row
< keypad
->rows
; row
++) {
128 if (!(changed
& (1 << row
)))
131 pressed
= row_state
[col
] & (1 << row
);
133 dev_dbg(&keypad
->input_dev
->dev
,
134 "key %s, row: %d, col: %d\n",
135 pressed
? "pressed" : "released", row
, col
);
137 val
= MATRIX_SCAN_CODE(row
, col
, keypad
->row_shift
);
139 input_event(input_dev
, EV_MSC
, MSC_SCAN
, val
);
140 input_report_key(input_dev
,
141 keypad
->keycodes
[val
], pressed
);
143 input_sync(keypad
->input_dev
);
146 memcpy(keypad
->row_state
, row_state
, sizeof(keypad
->row_state
));
151 static irqreturn_t
samsung_keypad_irq(int irq
, void *dev_id
)
153 struct samsung_keypad
*keypad
= dev_id
;
154 unsigned int row_state
[SAMSUNG_MAX_COLS
];
159 val
= readl(keypad
->base
+ SAMSUNG_KEYIFSTSCLR
);
160 /* Clear interrupt. */
161 writel(~0x0, keypad
->base
+ SAMSUNG_KEYIFSTSCLR
);
163 samsung_keypad_scan(keypad
, row_state
);
165 key_down
= samsung_keypad_report(keypad
, row_state
);
167 wait_event_timeout(keypad
->wait
, keypad
->stopped
,
168 msecs_to_jiffies(50));
170 } while (key_down
&& !keypad
->stopped
);
175 static void samsung_keypad_start(struct samsung_keypad
*keypad
)
179 /* Tell IRQ thread that it may poll the device. */
180 keypad
->stopped
= false;
182 clk_enable(keypad
->clk
);
184 /* Enable interrupt bits. */
185 val
= readl(keypad
->base
+ SAMSUNG_KEYIFCON
);
186 val
|= SAMSUNG_KEYIFCON_INT_F_EN
| SAMSUNG_KEYIFCON_INT_R_EN
;
187 writel(val
, keypad
->base
+ SAMSUNG_KEYIFCON
);
189 /* KEYIFCOL reg clear. */
190 writel(0, keypad
->base
+ SAMSUNG_KEYIFCOL
);
193 static void samsung_keypad_stop(struct samsung_keypad
*keypad
)
197 /* Signal IRQ thread to stop polling and disable the handler. */
198 keypad
->stopped
= true;
199 wake_up(&keypad
->wait
);
200 disable_irq(keypad
->irq
);
202 /* Clear interrupt. */
203 writel(~0x0, keypad
->base
+ SAMSUNG_KEYIFSTSCLR
);
205 /* Disable interrupt bits. */
206 val
= readl(keypad
->base
+ SAMSUNG_KEYIFCON
);
207 val
&= ~(SAMSUNG_KEYIFCON_INT_F_EN
| SAMSUNG_KEYIFCON_INT_R_EN
);
208 writel(val
, keypad
->base
+ SAMSUNG_KEYIFCON
);
210 clk_disable(keypad
->clk
);
213 * Now that chip should not generate interrupts we can safely
214 * re-enable the handler.
216 enable_irq(keypad
->irq
);
219 static int samsung_keypad_open(struct input_dev
*input_dev
)
221 struct samsung_keypad
*keypad
= input_get_drvdata(input_dev
);
223 samsung_keypad_start(keypad
);
228 static void samsung_keypad_close(struct input_dev
*input_dev
)
230 struct samsung_keypad
*keypad
= input_get_drvdata(input_dev
);
232 samsung_keypad_stop(keypad
);
236 static struct samsung_keypad_platdata
*samsung_keypad_parse_dt(
239 struct samsung_keypad_platdata
*pdata
;
240 struct matrix_keymap_data
*keymap_data
;
241 uint32_t *keymap
, num_rows
= 0, num_cols
= 0;
242 struct device_node
*np
= dev
->of_node
, *key_np
;
243 unsigned int key_count
= 0;
245 pdata
= devm_kzalloc(dev
, sizeof(*pdata
), GFP_KERNEL
);
247 dev_err(dev
, "could not allocate memory for platform data\n");
251 of_property_read_u32(np
, "samsung,keypad-num-rows", &num_rows
);
252 of_property_read_u32(np
, "samsung,keypad-num-columns", &num_cols
);
253 if (!num_rows
|| !num_cols
) {
254 dev_err(dev
, "number of keypad rows/columns not specified\n");
257 pdata
->rows
= num_rows
;
258 pdata
->cols
= num_cols
;
260 keymap_data
= devm_kzalloc(dev
, sizeof(*keymap_data
), GFP_KERNEL
);
262 dev_err(dev
, "could not allocate memory for keymap data\n");
265 pdata
->keymap_data
= keymap_data
;
267 for_each_child_of_node(np
, key_np
)
270 keymap_data
->keymap_size
= key_count
;
271 keymap
= devm_kzalloc(dev
, sizeof(uint32_t) * key_count
, GFP_KERNEL
);
273 dev_err(dev
, "could not allocate memory for keymap\n");
276 keymap_data
->keymap
= keymap
;
278 for_each_child_of_node(np
, key_np
) {
279 u32 row
, col
, key_code
;
280 of_property_read_u32(key_np
, "keypad,row", &row
);
281 of_property_read_u32(key_np
, "keypad,column", &col
);
282 of_property_read_u32(key_np
, "linux,code", &key_code
);
283 *keymap
++ = KEY(row
, col
, key_code
);
286 if (of_get_property(np
, "linux,input-no-autorepeat", NULL
))
287 pdata
->no_autorepeat
= true;
288 if (of_get_property(np
, "linux,input-wakeup", NULL
))
289 pdata
->wakeup
= true;
294 static void samsung_keypad_parse_dt_gpio(struct device
*dev
,
295 struct samsung_keypad
*keypad
)
297 struct device_node
*np
= dev
->of_node
;
298 int gpio
, ret
, row
, col
;
300 for (row
= 0; row
< keypad
->rows
; row
++) {
301 gpio
= of_get_named_gpio(np
, "row-gpios", row
);
302 keypad
->row_gpios
[row
] = gpio
;
303 if (!gpio_is_valid(gpio
)) {
304 dev_err(dev
, "keypad row[%d]: invalid gpio %d\n",
309 ret
= gpio_request(gpio
, "keypad-row");
311 dev_err(dev
, "keypad row[%d] gpio request failed\n",
315 for (col
= 0; col
< keypad
->cols
; col
++) {
316 gpio
= of_get_named_gpio(np
, "col-gpios", col
);
317 keypad
->col_gpios
[col
] = gpio
;
318 if (!gpio_is_valid(gpio
)) {
319 dev_err(dev
, "keypad column[%d]: invalid gpio %d\n",
324 ret
= gpio_request(gpio
, "keypad-col");
326 dev_err(dev
, "keypad column[%d] gpio request failed\n",
331 static void samsung_keypad_dt_gpio_free(struct samsung_keypad
*keypad
)
335 for (cnt
= 0; cnt
< keypad
->rows
; cnt
++)
336 if (gpio_is_valid(keypad
->row_gpios
[cnt
]))
337 gpio_free(keypad
->row_gpios
[cnt
]);
339 for (cnt
= 0; cnt
< keypad
->cols
; cnt
++)
340 if (gpio_is_valid(keypad
->col_gpios
[cnt
]))
341 gpio_free(keypad
->col_gpios
[cnt
]);
345 struct samsung_keypad_platdata
*samsung_keypad_parse_dt(struct device
*dev
)
350 static void samsung_keypad_dt_gpio_free(struct samsung_keypad
*keypad
)
355 static int __devinit
samsung_keypad_probe(struct platform_device
*pdev
)
357 const struct samsung_keypad_platdata
*pdata
;
358 const struct matrix_keymap_data
*keymap_data
;
359 struct samsung_keypad
*keypad
;
360 struct resource
*res
;
361 struct input_dev
*input_dev
;
362 unsigned int row_shift
;
363 unsigned int keymap_size
;
366 if (pdev
->dev
.of_node
)
367 pdata
= samsung_keypad_parse_dt(&pdev
->dev
);
369 pdata
= pdev
->dev
.platform_data
;
371 dev_err(&pdev
->dev
, "no platform data defined\n");
375 keymap_data
= pdata
->keymap_data
;
377 dev_err(&pdev
->dev
, "no keymap data defined\n");
381 if (!pdata
->rows
|| pdata
->rows
> SAMSUNG_MAX_ROWS
)
384 if (!pdata
->cols
|| pdata
->cols
> SAMSUNG_MAX_COLS
)
387 /* initialize the gpio */
389 pdata
->cfg_gpio(pdata
->rows
, pdata
->cols
);
391 row_shift
= get_count_order(pdata
->cols
);
392 keymap_size
= (pdata
->rows
<< row_shift
) * sizeof(keypad
->keycodes
[0]);
394 keypad
= kzalloc(sizeof(*keypad
) + keymap_size
, GFP_KERNEL
);
395 input_dev
= input_allocate_device();
396 if (!keypad
|| !input_dev
) {
401 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
407 keypad
->base
= ioremap(res
->start
, resource_size(res
));
413 keypad
->clk
= clk_get(&pdev
->dev
, "keypad");
414 if (IS_ERR(keypad
->clk
)) {
415 dev_err(&pdev
->dev
, "failed to get keypad clk\n");
416 error
= PTR_ERR(keypad
->clk
);
420 keypad
->input_dev
= input_dev
;
421 keypad
->row_shift
= row_shift
;
422 keypad
->rows
= pdata
->rows
;
423 keypad
->cols
= pdata
->cols
;
424 init_waitqueue_head(&keypad
->wait
);
426 if (pdev
->dev
.of_node
) {
428 samsung_keypad_parse_dt_gpio(&pdev
->dev
, keypad
);
429 keypad
->type
= of_device_is_compatible(pdev
->dev
.of_node
,
430 "samsung,s5pv210-keypad");
433 keypad
->type
= platform_get_device_id(pdev
)->driver_data
;
436 input_dev
->name
= pdev
->name
;
437 input_dev
->id
.bustype
= BUS_HOST
;
438 input_dev
->dev
.parent
= &pdev
->dev
;
439 input_set_drvdata(input_dev
, keypad
);
441 input_dev
->open
= samsung_keypad_open
;
442 input_dev
->close
= samsung_keypad_close
;
444 input_dev
->evbit
[0] = BIT_MASK(EV_KEY
);
445 if (!pdata
->no_autorepeat
)
446 input_dev
->evbit
[0] |= BIT_MASK(EV_REP
);
448 input_set_capability(input_dev
, EV_MSC
, MSC_SCAN
);
450 input_dev
->keycode
= keypad
->keycodes
;
451 input_dev
->keycodesize
= sizeof(keypad
->keycodes
[0]);
452 input_dev
->keycodemax
= pdata
->rows
<< row_shift
;
454 matrix_keypad_build_keymap(keymap_data
, row_shift
,
455 input_dev
->keycode
, input_dev
->keybit
);
457 keypad
->irq
= platform_get_irq(pdev
, 0);
458 if (keypad
->irq
< 0) {
463 error
= request_threaded_irq(keypad
->irq
, NULL
, samsung_keypad_irq
,
464 IRQF_ONESHOT
, dev_name(&pdev
->dev
), keypad
);
466 dev_err(&pdev
->dev
, "failed to register keypad interrupt\n");
470 error
= input_register_device(keypad
->input_dev
);
474 device_init_wakeup(&pdev
->dev
, pdata
->wakeup
);
475 platform_set_drvdata(pdev
, keypad
);
477 if (pdev
->dev
.of_node
) {
478 devm_kfree(&pdev
->dev
, (void *)pdata
->keymap_data
->keymap
);
479 devm_kfree(&pdev
->dev
, (void *)pdata
->keymap_data
);
480 devm_kfree(&pdev
->dev
, (void *)pdata
);
485 free_irq(keypad
->irq
, keypad
);
487 clk_put(keypad
->clk
);
488 samsung_keypad_dt_gpio_free(keypad
);
490 iounmap(keypad
->base
);
492 input_free_device(input_dev
);
498 static int __devexit
samsung_keypad_remove(struct platform_device
*pdev
)
500 struct samsung_keypad
*keypad
= platform_get_drvdata(pdev
);
502 device_init_wakeup(&pdev
->dev
, 0);
503 platform_set_drvdata(pdev
, NULL
);
505 input_unregister_device(keypad
->input_dev
);
508 * It is safe to free IRQ after unregistering device because
509 * samsung_keypad_close will shut off interrupts.
511 free_irq(keypad
->irq
, keypad
);
513 clk_put(keypad
->clk
);
514 samsung_keypad_dt_gpio_free(keypad
);
516 iounmap(keypad
->base
);
523 static void samsung_keypad_toggle_wakeup(struct samsung_keypad
*keypad
,
526 struct device
*dev
= keypad
->input_dev
->dev
.parent
;
529 clk_enable(keypad
->clk
);
531 val
= readl(keypad
->base
+ SAMSUNG_KEYIFCON
);
533 val
|= SAMSUNG_KEYIFCON_WAKEUPEN
;
534 if (device_may_wakeup(dev
))
535 enable_irq_wake(keypad
->irq
);
537 val
&= ~SAMSUNG_KEYIFCON_WAKEUPEN
;
538 if (device_may_wakeup(dev
))
539 disable_irq_wake(keypad
->irq
);
541 writel(val
, keypad
->base
+ SAMSUNG_KEYIFCON
);
543 clk_disable(keypad
->clk
);
546 static int samsung_keypad_suspend(struct device
*dev
)
548 struct platform_device
*pdev
= to_platform_device(dev
);
549 struct samsung_keypad
*keypad
= platform_get_drvdata(pdev
);
550 struct input_dev
*input_dev
= keypad
->input_dev
;
552 mutex_lock(&input_dev
->mutex
);
554 if (input_dev
->users
)
555 samsung_keypad_stop(keypad
);
557 samsung_keypad_toggle_wakeup(keypad
, true);
559 mutex_unlock(&input_dev
->mutex
);
564 static int samsung_keypad_resume(struct device
*dev
)
566 struct platform_device
*pdev
= to_platform_device(dev
);
567 struct samsung_keypad
*keypad
= platform_get_drvdata(pdev
);
568 struct input_dev
*input_dev
= keypad
->input_dev
;
570 mutex_lock(&input_dev
->mutex
);
572 samsung_keypad_toggle_wakeup(keypad
, false);
574 if (input_dev
->users
)
575 samsung_keypad_start(keypad
);
577 mutex_unlock(&input_dev
->mutex
);
582 static const struct dev_pm_ops samsung_keypad_pm_ops
= {
583 .suspend
= samsung_keypad_suspend
,
584 .resume
= samsung_keypad_resume
,
589 static const struct of_device_id samsung_keypad_dt_match
[] = {
590 { .compatible
= "samsung,s3c6410-keypad" },
591 { .compatible
= "samsung,s5pv210-keypad" },
594 MODULE_DEVICE_TABLE(of
, samsung_keypad_dt_match
);
596 #define samsung_keypad_dt_match NULL
599 static struct platform_device_id samsung_keypad_driver_ids
[] = {
601 .name
= "samsung-keypad",
602 .driver_data
= KEYPAD_TYPE_SAMSUNG
,
604 .name
= "s5pv210-keypad",
605 .driver_data
= KEYPAD_TYPE_S5PV210
,
609 MODULE_DEVICE_TABLE(platform
, samsung_keypad_driver_ids
);
611 static struct platform_driver samsung_keypad_driver
= {
612 .probe
= samsung_keypad_probe
,
613 .remove
= __devexit_p(samsung_keypad_remove
),
615 .name
= "samsung-keypad",
616 .owner
= THIS_MODULE
,
617 .of_match_table
= samsung_keypad_dt_match
,
619 .pm
= &samsung_keypad_pm_ops
,
622 .id_table
= samsung_keypad_driver_ids
,
625 static int __init
samsung_keypad_init(void)
627 return platform_driver_register(&samsung_keypad_driver
);
629 module_init(samsung_keypad_init
);
631 static void __exit
samsung_keypad_exit(void)
633 platform_driver_unregister(&samsung_keypad_driver
);
635 module_exit(samsung_keypad_exit
);
637 MODULE_DESCRIPTION("Samsung keypad driver");
638 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
639 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
640 MODULE_LICENSE("GPL");
641 MODULE_ALIAS("platform:samsung-keypad");