Merge tag 'for-5.3-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / drivers / input / keyboard / samsung-keypad.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Samsung keypad driver
4  *
5  * Copyright (C) 2010 Samsung Electronics Co.Ltd
6  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
7  * Author: Donghwa Lee <dh09.lee@samsung.com>
8  */
9
10 #include <linux/clk.h>
11 #include <linux/delay.h>
12 #include <linux/err.h>
13 #include <linux/input.h>
14 #include <linux/interrupt.h>
15 #include <linux/io.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/pm.h>
19 #include <linux/pm_runtime.h>
20 #include <linux/slab.h>
21 #include <linux/of.h>
22 #include <linux/sched.h>
23 #include <linux/input/samsung-keypad.h>
24
25 #define SAMSUNG_KEYIFCON                        0x00
26 #define SAMSUNG_KEYIFSTSCLR                     0x04
27 #define SAMSUNG_KEYIFCOL                        0x08
28 #define SAMSUNG_KEYIFROW                        0x0c
29 #define SAMSUNG_KEYIFFC                         0x10
30
31 /* SAMSUNG_KEYIFCON */
32 #define SAMSUNG_KEYIFCON_INT_F_EN               (1 << 0)
33 #define SAMSUNG_KEYIFCON_INT_R_EN               (1 << 1)
34 #define SAMSUNG_KEYIFCON_DF_EN                  (1 << 2)
35 #define SAMSUNG_KEYIFCON_FC_EN                  (1 << 3)
36 #define SAMSUNG_KEYIFCON_WAKEUPEN               (1 << 4)
37
38 /* SAMSUNG_KEYIFSTSCLR */
39 #define SAMSUNG_KEYIFSTSCLR_P_INT_MASK          (0xff << 0)
40 #define SAMSUNG_KEYIFSTSCLR_R_INT_MASK          (0xff << 8)
41 #define SAMSUNG_KEYIFSTSCLR_R_INT_OFFSET        8
42 #define S5PV210_KEYIFSTSCLR_P_INT_MASK          (0x3fff << 0)
43 #define S5PV210_KEYIFSTSCLR_R_INT_MASK          (0x3fff << 16)
44 #define S5PV210_KEYIFSTSCLR_R_INT_OFFSET        16
45
46 /* SAMSUNG_KEYIFCOL */
47 #define SAMSUNG_KEYIFCOL_MASK                   (0xff << 0)
48 #define S5PV210_KEYIFCOLEN_MASK                 (0xff << 8)
49
50 /* SAMSUNG_KEYIFROW */
51 #define SAMSUNG_KEYIFROW_MASK                   (0xff << 0)
52 #define S5PV210_KEYIFROW_MASK                   (0x3fff << 0)
53
54 /* SAMSUNG_KEYIFFC */
55 #define SAMSUNG_KEYIFFC_MASK                    (0x3ff << 0)
56
57 enum samsung_keypad_type {
58         KEYPAD_TYPE_SAMSUNG,
59         KEYPAD_TYPE_S5PV210,
60 };
61
62 struct samsung_keypad {
63         struct input_dev *input_dev;
64         struct platform_device *pdev;
65         struct clk *clk;
66         void __iomem *base;
67         wait_queue_head_t wait;
68         bool stopped;
69         bool wake_enabled;
70         int irq;
71         enum samsung_keypad_type type;
72         unsigned int row_shift;
73         unsigned int rows;
74         unsigned int cols;
75         unsigned int row_state[SAMSUNG_MAX_COLS];
76         unsigned short keycodes[];
77 };
78
79 static void samsung_keypad_scan(struct samsung_keypad *keypad,
80                                 unsigned int *row_state)
81 {
82         unsigned int col;
83         unsigned int val;
84
85         for (col = 0; col < keypad->cols; col++) {
86                 if (keypad->type == KEYPAD_TYPE_S5PV210) {
87                         val = S5PV210_KEYIFCOLEN_MASK;
88                         val &= ~(1 << col) << 8;
89                 } else {
90                         val = SAMSUNG_KEYIFCOL_MASK;
91                         val &= ~(1 << col);
92                 }
93
94                 writel(val, keypad->base + SAMSUNG_KEYIFCOL);
95                 mdelay(1);
96
97                 val = readl(keypad->base + SAMSUNG_KEYIFROW);
98                 row_state[col] = ~val & ((1 << keypad->rows) - 1);
99         }
100
101         /* KEYIFCOL reg clear */
102         writel(0, keypad->base + SAMSUNG_KEYIFCOL);
103 }
104
105 static bool samsung_keypad_report(struct samsung_keypad *keypad,
106                                   unsigned int *row_state)
107 {
108         struct input_dev *input_dev = keypad->input_dev;
109         unsigned int changed;
110         unsigned int pressed;
111         unsigned int key_down = 0;
112         unsigned int val;
113         unsigned int col, row;
114
115         for (col = 0; col < keypad->cols; col++) {
116                 changed = row_state[col] ^ keypad->row_state[col];
117                 key_down |= row_state[col];
118                 if (!changed)
119                         continue;
120
121                 for (row = 0; row < keypad->rows; row++) {
122                         if (!(changed & (1 << row)))
123                                 continue;
124
125                         pressed = row_state[col] & (1 << row);
126
127                         dev_dbg(&keypad->input_dev->dev,
128                                 "key %s, row: %d, col: %d\n",
129                                 pressed ? "pressed" : "released", row, col);
130
131                         val = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
132
133                         input_event(input_dev, EV_MSC, MSC_SCAN, val);
134                         input_report_key(input_dev,
135                                         keypad->keycodes[val], pressed);
136                 }
137                 input_sync(keypad->input_dev);
138         }
139
140         memcpy(keypad->row_state, row_state, sizeof(keypad->row_state));
141
142         return key_down;
143 }
144
145 static irqreturn_t samsung_keypad_irq(int irq, void *dev_id)
146 {
147         struct samsung_keypad *keypad = dev_id;
148         unsigned int row_state[SAMSUNG_MAX_COLS];
149         unsigned int val;
150         bool key_down;
151
152         pm_runtime_get_sync(&keypad->pdev->dev);
153
154         do {
155                 val = readl(keypad->base + SAMSUNG_KEYIFSTSCLR);
156                 /* Clear interrupt. */
157                 writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR);
158
159                 samsung_keypad_scan(keypad, row_state);
160
161                 key_down = samsung_keypad_report(keypad, row_state);
162                 if (key_down)
163                         wait_event_timeout(keypad->wait, keypad->stopped,
164                                            msecs_to_jiffies(50));
165
166         } while (key_down && !keypad->stopped);
167
168         pm_runtime_put(&keypad->pdev->dev);
169
170         return IRQ_HANDLED;
171 }
172
173 static void samsung_keypad_start(struct samsung_keypad *keypad)
174 {
175         unsigned int val;
176
177         pm_runtime_get_sync(&keypad->pdev->dev);
178
179         /* Tell IRQ thread that it may poll the device. */
180         keypad->stopped = false;
181
182         clk_enable(keypad->clk);
183
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);
188
189         /* KEYIFCOL reg clear. */
190         writel(0, keypad->base + SAMSUNG_KEYIFCOL);
191
192         pm_runtime_put(&keypad->pdev->dev);
193 }
194
195 static void samsung_keypad_stop(struct samsung_keypad *keypad)
196 {
197         unsigned int val;
198
199         pm_runtime_get_sync(&keypad->pdev->dev);
200
201         /* Signal IRQ thread to stop polling and disable the handler. */
202         keypad->stopped = true;
203         wake_up(&keypad->wait);
204         disable_irq(keypad->irq);
205
206         /* Clear interrupt. */
207         writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR);
208
209         /* Disable interrupt bits. */
210         val = readl(keypad->base + SAMSUNG_KEYIFCON);
211         val &= ~(SAMSUNG_KEYIFCON_INT_F_EN | SAMSUNG_KEYIFCON_INT_R_EN);
212         writel(val, keypad->base + SAMSUNG_KEYIFCON);
213
214         clk_disable(keypad->clk);
215
216         /*
217          * Now that chip should not generate interrupts we can safely
218          * re-enable the handler.
219          */
220         enable_irq(keypad->irq);
221
222         pm_runtime_put(&keypad->pdev->dev);
223 }
224
225 static int samsung_keypad_open(struct input_dev *input_dev)
226 {
227         struct samsung_keypad *keypad = input_get_drvdata(input_dev);
228
229         samsung_keypad_start(keypad);
230
231         return 0;
232 }
233
234 static void samsung_keypad_close(struct input_dev *input_dev)
235 {
236         struct samsung_keypad *keypad = input_get_drvdata(input_dev);
237
238         samsung_keypad_stop(keypad);
239 }
240
241 #ifdef CONFIG_OF
242 static struct samsung_keypad_platdata *
243 samsung_keypad_parse_dt(struct device *dev)
244 {
245         struct samsung_keypad_platdata *pdata;
246         struct matrix_keymap_data *keymap_data;
247         uint32_t *keymap, num_rows = 0, num_cols = 0;
248         struct device_node *np = dev->of_node, *key_np;
249         unsigned int key_count;
250
251         if (!np) {
252                 dev_err(dev, "missing device tree data\n");
253                 return ERR_PTR(-EINVAL);
254         }
255
256         pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
257         if (!pdata) {
258                 dev_err(dev, "could not allocate memory for platform data\n");
259                 return ERR_PTR(-ENOMEM);
260         }
261
262         of_property_read_u32(np, "samsung,keypad-num-rows", &num_rows);
263         of_property_read_u32(np, "samsung,keypad-num-columns", &num_cols);
264         if (!num_rows || !num_cols) {
265                 dev_err(dev, "number of keypad rows/columns not specified\n");
266                 return ERR_PTR(-EINVAL);
267         }
268         pdata->rows = num_rows;
269         pdata->cols = num_cols;
270
271         keymap_data = devm_kzalloc(dev, sizeof(*keymap_data), GFP_KERNEL);
272         if (!keymap_data) {
273                 dev_err(dev, "could not allocate memory for keymap data\n");
274                 return ERR_PTR(-ENOMEM);
275         }
276         pdata->keymap_data = keymap_data;
277
278         key_count = of_get_child_count(np);
279         keymap_data->keymap_size = key_count;
280         keymap = devm_kcalloc(dev, key_count, sizeof(uint32_t), GFP_KERNEL);
281         if (!keymap) {
282                 dev_err(dev, "could not allocate memory for keymap\n");
283                 return ERR_PTR(-ENOMEM);
284         }
285         keymap_data->keymap = keymap;
286
287         for_each_child_of_node(np, key_np) {
288                 u32 row, col, key_code;
289                 of_property_read_u32(key_np, "keypad,row", &row);
290                 of_property_read_u32(key_np, "keypad,column", &col);
291                 of_property_read_u32(key_np, "linux,code", &key_code);
292                 *keymap++ = KEY(row, col, key_code);
293         }
294
295         if (of_get_property(np, "linux,input-no-autorepeat", NULL))
296                 pdata->no_autorepeat = true;
297
298         pdata->wakeup = of_property_read_bool(np, "wakeup-source") ||
299                         /* legacy name */
300                         of_property_read_bool(np, "linux,input-wakeup");
301
302
303         return pdata;
304 }
305 #else
306 static struct samsung_keypad_platdata *
307 samsung_keypad_parse_dt(struct device *dev)
308 {
309         dev_err(dev, "no platform data defined\n");
310
311         return ERR_PTR(-EINVAL);
312 }
313 #endif
314
315 static int samsung_keypad_probe(struct platform_device *pdev)
316 {
317         const struct samsung_keypad_platdata *pdata;
318         const struct matrix_keymap_data *keymap_data;
319         struct samsung_keypad *keypad;
320         struct resource *res;
321         struct input_dev *input_dev;
322         unsigned int row_shift;
323         unsigned int keymap_size;
324         int error;
325
326         pdata = dev_get_platdata(&pdev->dev);
327         if (!pdata) {
328                 pdata = samsung_keypad_parse_dt(&pdev->dev);
329                 if (IS_ERR(pdata))
330                         return PTR_ERR(pdata);
331         }
332
333         keymap_data = pdata->keymap_data;
334         if (!keymap_data) {
335                 dev_err(&pdev->dev, "no keymap data defined\n");
336                 return -EINVAL;
337         }
338
339         if (!pdata->rows || pdata->rows > SAMSUNG_MAX_ROWS)
340                 return -EINVAL;
341
342         if (!pdata->cols || pdata->cols > SAMSUNG_MAX_COLS)
343                 return -EINVAL;
344
345         /* initialize the gpio */
346         if (pdata->cfg_gpio)
347                 pdata->cfg_gpio(pdata->rows, pdata->cols);
348
349         row_shift = get_count_order(pdata->cols);
350         keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]);
351
352         keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad) + keymap_size,
353                               GFP_KERNEL);
354         input_dev = devm_input_allocate_device(&pdev->dev);
355         if (!keypad || !input_dev)
356                 return -ENOMEM;
357
358         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
359         if (!res)
360                 return -ENODEV;
361
362         keypad->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
363         if (!keypad->base)
364                 return -EBUSY;
365
366         keypad->clk = devm_clk_get(&pdev->dev, "keypad");
367         if (IS_ERR(keypad->clk)) {
368                 dev_err(&pdev->dev, "failed to get keypad clk\n");
369                 return PTR_ERR(keypad->clk);
370         }
371
372         error = clk_prepare(keypad->clk);
373         if (error) {
374                 dev_err(&pdev->dev, "keypad clock prepare failed\n");
375                 return error;
376         }
377
378         keypad->input_dev = input_dev;
379         keypad->pdev = pdev;
380         keypad->row_shift = row_shift;
381         keypad->rows = pdata->rows;
382         keypad->cols = pdata->cols;
383         keypad->stopped = true;
384         init_waitqueue_head(&keypad->wait);
385
386         if (pdev->dev.of_node)
387                 keypad->type = of_device_is_compatible(pdev->dev.of_node,
388                                         "samsung,s5pv210-keypad");
389         else
390                 keypad->type = platform_get_device_id(pdev)->driver_data;
391
392         input_dev->name = pdev->name;
393         input_dev->id.bustype = BUS_HOST;
394         input_dev->dev.parent = &pdev->dev;
395
396         input_dev->open = samsung_keypad_open;
397         input_dev->close = samsung_keypad_close;
398
399         error = matrix_keypad_build_keymap(keymap_data, NULL,
400                                            pdata->rows, pdata->cols,
401                                            keypad->keycodes, input_dev);
402         if (error) {
403                 dev_err(&pdev->dev, "failed to build keymap\n");
404                 goto err_unprepare_clk;
405         }
406
407         input_set_capability(input_dev, EV_MSC, MSC_SCAN);
408         if (!pdata->no_autorepeat)
409                 __set_bit(EV_REP, input_dev->evbit);
410
411         input_set_drvdata(input_dev, keypad);
412
413         keypad->irq = platform_get_irq(pdev, 0);
414         if (keypad->irq < 0) {
415                 error = keypad->irq;
416                 goto err_unprepare_clk;
417         }
418
419         error = devm_request_threaded_irq(&pdev->dev, keypad->irq, NULL,
420                                           samsung_keypad_irq, IRQF_ONESHOT,
421                                           dev_name(&pdev->dev), keypad);
422         if (error) {
423                 dev_err(&pdev->dev, "failed to register keypad interrupt\n");
424                 goto err_unprepare_clk;
425         }
426
427         device_init_wakeup(&pdev->dev, pdata->wakeup);
428         platform_set_drvdata(pdev, keypad);
429         pm_runtime_enable(&pdev->dev);
430
431         error = input_register_device(keypad->input_dev);
432         if (error)
433                 goto err_disable_runtime_pm;
434
435         if (pdev->dev.of_node) {
436                 devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap);
437                 devm_kfree(&pdev->dev, (void *)pdata->keymap_data);
438                 devm_kfree(&pdev->dev, (void *)pdata);
439         }
440         return 0;
441
442 err_disable_runtime_pm:
443         pm_runtime_disable(&pdev->dev);
444 err_unprepare_clk:
445         clk_unprepare(keypad->clk);
446         return error;
447 }
448
449 static int samsung_keypad_remove(struct platform_device *pdev)
450 {
451         struct samsung_keypad *keypad = platform_get_drvdata(pdev);
452
453         pm_runtime_disable(&pdev->dev);
454
455         input_unregister_device(keypad->input_dev);
456
457         clk_unprepare(keypad->clk);
458
459         return 0;
460 }
461
462 #ifdef CONFIG_PM
463 static int samsung_keypad_runtime_suspend(struct device *dev)
464 {
465         struct platform_device *pdev = to_platform_device(dev);
466         struct samsung_keypad *keypad = platform_get_drvdata(pdev);
467         unsigned int val;
468         int error;
469
470         if (keypad->stopped)
471                 return 0;
472
473         /* This may fail on some SoCs due to lack of controller support */
474         error = enable_irq_wake(keypad->irq);
475         if (!error)
476                 keypad->wake_enabled = true;
477
478         val = readl(keypad->base + SAMSUNG_KEYIFCON);
479         val |= SAMSUNG_KEYIFCON_WAKEUPEN;
480         writel(val, keypad->base + SAMSUNG_KEYIFCON);
481
482         clk_disable(keypad->clk);
483
484         return 0;
485 }
486
487 static int samsung_keypad_runtime_resume(struct device *dev)
488 {
489         struct platform_device *pdev = to_platform_device(dev);
490         struct samsung_keypad *keypad = platform_get_drvdata(pdev);
491         unsigned int val;
492
493         if (keypad->stopped)
494                 return 0;
495
496         clk_enable(keypad->clk);
497
498         val = readl(keypad->base + SAMSUNG_KEYIFCON);
499         val &= ~SAMSUNG_KEYIFCON_WAKEUPEN;
500         writel(val, keypad->base + SAMSUNG_KEYIFCON);
501
502         if (keypad->wake_enabled)
503                 disable_irq_wake(keypad->irq);
504
505         return 0;
506 }
507 #endif
508
509 #ifdef CONFIG_PM_SLEEP
510 static void samsung_keypad_toggle_wakeup(struct samsung_keypad *keypad,
511                                          bool enable)
512 {
513         unsigned int val;
514
515         clk_enable(keypad->clk);
516
517         val = readl(keypad->base + SAMSUNG_KEYIFCON);
518         if (enable) {
519                 val |= SAMSUNG_KEYIFCON_WAKEUPEN;
520                 if (device_may_wakeup(&keypad->pdev->dev))
521                         enable_irq_wake(keypad->irq);
522         } else {
523                 val &= ~SAMSUNG_KEYIFCON_WAKEUPEN;
524                 if (device_may_wakeup(&keypad->pdev->dev))
525                         disable_irq_wake(keypad->irq);
526         }
527         writel(val, keypad->base + SAMSUNG_KEYIFCON);
528
529         clk_disable(keypad->clk);
530 }
531
532 static int samsung_keypad_suspend(struct device *dev)
533 {
534         struct platform_device *pdev = to_platform_device(dev);
535         struct samsung_keypad *keypad = platform_get_drvdata(pdev);
536         struct input_dev *input_dev = keypad->input_dev;
537
538         mutex_lock(&input_dev->mutex);
539
540         if (input_dev->users)
541                 samsung_keypad_stop(keypad);
542
543         samsung_keypad_toggle_wakeup(keypad, true);
544
545         mutex_unlock(&input_dev->mutex);
546
547         return 0;
548 }
549
550 static int samsung_keypad_resume(struct device *dev)
551 {
552         struct platform_device *pdev = to_platform_device(dev);
553         struct samsung_keypad *keypad = platform_get_drvdata(pdev);
554         struct input_dev *input_dev = keypad->input_dev;
555
556         mutex_lock(&input_dev->mutex);
557
558         samsung_keypad_toggle_wakeup(keypad, false);
559
560         if (input_dev->users)
561                 samsung_keypad_start(keypad);
562
563         mutex_unlock(&input_dev->mutex);
564
565         return 0;
566 }
567 #endif
568
569 static const struct dev_pm_ops samsung_keypad_pm_ops = {
570         SET_SYSTEM_SLEEP_PM_OPS(samsung_keypad_suspend, samsung_keypad_resume)
571         SET_RUNTIME_PM_OPS(samsung_keypad_runtime_suspend,
572                            samsung_keypad_runtime_resume, NULL)
573 };
574
575 #ifdef CONFIG_OF
576 static const struct of_device_id samsung_keypad_dt_match[] = {
577         { .compatible = "samsung,s3c6410-keypad" },
578         { .compatible = "samsung,s5pv210-keypad" },
579         {},
580 };
581 MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match);
582 #endif
583
584 static const struct platform_device_id samsung_keypad_driver_ids[] = {
585         {
586                 .name           = "samsung-keypad",
587                 .driver_data    = KEYPAD_TYPE_SAMSUNG,
588         }, {
589                 .name           = "s5pv210-keypad",
590                 .driver_data    = KEYPAD_TYPE_S5PV210,
591         },
592         { },
593 };
594 MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids);
595
596 static struct platform_driver samsung_keypad_driver = {
597         .probe          = samsung_keypad_probe,
598         .remove         = samsung_keypad_remove,
599         .driver         = {
600                 .name   = "samsung-keypad",
601                 .of_match_table = of_match_ptr(samsung_keypad_dt_match),
602                 .pm     = &samsung_keypad_pm_ops,
603         },
604         .id_table       = samsung_keypad_driver_ids,
605 };
606 module_platform_driver(samsung_keypad_driver);
607
608 MODULE_DESCRIPTION("Samsung keypad driver");
609 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
610 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
611 MODULE_LICENSE("GPL");