Version:  2.0.40 2.2.26 2.4.37 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6

Linux/drivers/input/keyboard/tc3589x-keypad.c

  1 /*
  2  * Copyright (C) ST-Ericsson SA 2010
  3  *
  4  * Author: Jayeeta Banerjee <jayeeta.banerjee@stericsson.com>
  5  * Author: Sundar Iyer <sundar.iyer@stericsson.com>
  6  *
  7  * License Terms: GNU General Public License, version 2
  8  *
  9  * TC35893 MFD Keypad Controller driver
 10  */
 11 
 12 #include <linux/module.h>
 13 #include <linux/interrupt.h>
 14 #include <linux/input.h>
 15 #include <linux/platform_device.h>
 16 #include <linux/input/matrix_keypad.h>
 17 #include <linux/i2c.h>
 18 #include <linux/slab.h>
 19 #include <linux/mfd/tc3589x.h>
 20 #include <linux/device.h>
 21 
 22 /* Maximum supported keypad matrix row/columns size */
 23 #define TC3589x_MAX_KPROW               8
 24 #define TC3589x_MAX_KPCOL               12
 25 
 26 /* keypad related Constants */
 27 #define TC3589x_MAX_DEBOUNCE_SETTLE     0xFF
 28 #define DEDICATED_KEY_VAL               0xFF
 29 
 30 /* Pull up/down masks */
 31 #define TC3589x_NO_PULL_MASK            0x0
 32 #define TC3589x_PULL_DOWN_MASK          0x1
 33 #define TC3589x_PULL_UP_MASK            0x2
 34 #define TC3589x_PULLUP_ALL_MASK         0xAA
 35 #define TC3589x_IO_PULL_VAL(index, mask)        ((mask)<<((index)%4)*2))
 36 
 37 /* Bit masks for IOCFG register */
 38 #define IOCFG_BALLCFG           0x01
 39 #define IOCFG_IG                0x08
 40 
 41 #define KP_EVCODE_COL_MASK      0x0F
 42 #define KP_EVCODE_ROW_MASK      0x70
 43 #define KP_RELEASE_EVT_MASK     0x80
 44 
 45 #define KP_ROW_SHIFT            4
 46 
 47 #define KP_NO_VALID_KEY_MASK    0x7F
 48 
 49 /* bit masks for RESTCTRL register */
 50 #define TC3589x_KBDRST          0x2
 51 #define TC3589x_IRQRST          0x10
 52 #define TC3589x_RESET_ALL       0x1B
 53 
 54 /* KBDMFS register bit mask */
 55 #define TC3589x_KBDMFS_EN       0x1
 56 
 57 /* CLKEN register bitmask */
 58 #define KPD_CLK_EN              0x1
 59 
 60 /* RSTINTCLR register bit mask */
 61 #define IRQ_CLEAR               0x1
 62 
 63 /* bit masks for keyboard interrupts*/
 64 #define TC3589x_EVT_LOSS_INT    0x8
 65 #define TC3589x_EVT_INT         0x4
 66 #define TC3589x_KBD_LOSS_INT    0x2
 67 #define TC3589x_KBD_INT         0x1
 68 
 69 /* bit masks for keyboard interrupt clear*/
 70 #define TC3589x_EVT_INT_CLR     0x2
 71 #define TC3589x_KBD_INT_CLR     0x1
 72 
 73 /**
 74  * struct tc35893_keypad_platform_data - platform specific keypad data
 75  * @keymap_data:        matrix scan code table for keycodes
 76  * @krow:               mask for available rows, value is 0xFF
 77  * @kcol:               mask for available columns, value is 0xFF
 78  * @debounce_period:    platform specific debounce time
 79  * @settle_time:        platform specific settle down time
 80  * @irqtype:            type of interrupt, falling or rising edge
 81  * @enable_wakeup:      specifies if keypad event can wake up system from sleep
 82  * @no_autorepeat:      flag for auto repetition
 83  */
 84 struct tc3589x_keypad_platform_data {
 85         const struct matrix_keymap_data *keymap_data;
 86         u8                      krow;
 87         u8                      kcol;
 88         u8                      debounce_period;
 89         u8                      settle_time;
 90         unsigned long           irqtype;
 91         bool                    enable_wakeup;
 92         bool                    no_autorepeat;
 93 };
 94 
 95 /**
 96  * struct tc_keypad - data structure used by keypad driver
 97  * @tc3589x:    pointer to tc35893
 98  * @input:      pointer to input device object
 99  * @board:      keypad platform device
100  * @krow:       number of rows
101  * @kcol:       number of columns
102  * @keymap:     matrix scan code table for keycodes
103  * @keypad_stopped: holds keypad status
104  */
105 struct tc_keypad {
106         struct tc3589x *tc3589x;
107         struct input_dev *input;
108         const struct tc3589x_keypad_platform_data *board;
109         unsigned int krow;
110         unsigned int kcol;
111         unsigned short *keymap;
112         bool keypad_stopped;
113 };
114 
115 static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
116 {
117         int ret;
118         struct tc3589x *tc3589x = keypad->tc3589x;
119         const struct tc3589x_keypad_platform_data *board = keypad->board;
120 
121         /* validate platform configuration */
122         if (board->kcol > TC3589x_MAX_KPCOL || board->krow > TC3589x_MAX_KPROW)
123                 return -EINVAL;
124 
125         /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */
126         ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE,
127                         (board->krow << KP_ROW_SHIFT) | board->kcol);
128         if (ret < 0)
129                 return ret;
130 
131         /* configure dedicated key config, no dedicated key selected */
132         ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_LSB, DEDICATED_KEY_VAL);
133         if (ret < 0)
134                 return ret;
135 
136         ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_MSB, DEDICATED_KEY_VAL);
137         if (ret < 0)
138                 return ret;
139 
140         /* Configure settle time */
141         ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG,
142                                 board->settle_time);
143         if (ret < 0)
144                 return ret;
145 
146         /* Configure debounce time */
147         ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE,
148                                 board->debounce_period);
149         if (ret < 0)
150                 return ret;
151 
152         /* Start of initialise keypad GPIOs */
153         ret = tc3589x_set_bits(tc3589x, TC3589x_IOCFG, 0x0, IOCFG_IG);
154         if (ret < 0)
155                 return ret;
156 
157         /* Configure pull-up resistors for all row GPIOs */
158         ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_LSB,
159                                         TC3589x_PULLUP_ALL_MASK);
160         if (ret < 0)
161                 return ret;
162 
163         ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_MSB,
164                                         TC3589x_PULLUP_ALL_MASK);
165         if (ret < 0)
166                 return ret;
167 
168         /* Configure pull-up resistors for all column GPIOs */
169         ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_LSB,
170                         TC3589x_PULLUP_ALL_MASK);
171         if (ret < 0)
172                 return ret;
173 
174         ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_MSB,
175                         TC3589x_PULLUP_ALL_MASK);
176         if (ret < 0)
177                 return ret;
178 
179         ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG2_LSB,
180                         TC3589x_PULLUP_ALL_MASK);
181 
182         return ret;
183 }
184 
185 #define TC35893_DATA_REGS               4
186 #define TC35893_KEYCODE_FIFO_EMPTY      0x7f
187 #define TC35893_KEYCODE_FIFO_CLEAR      0xff
188 #define TC35893_KEYPAD_ROW_SHIFT        0x3
189 
190 static irqreturn_t tc3589x_keypad_irq(int irq, void *dev)
191 {
192         struct tc_keypad *keypad = dev;
193         struct tc3589x *tc3589x = keypad->tc3589x;
194         u8 i, row_index, col_index, kbd_code, up;
195         u8 code;
196 
197         for (i = 0; i < TC35893_DATA_REGS * 2; i++) {
198                 kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO);
199 
200                 /* loop till fifo is empty and no more keys are pressed */
201                 if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY ||
202                                 kbd_code == TC35893_KEYCODE_FIFO_CLEAR)
203                         continue;
204 
205                 /* valid key is found */
206                 col_index = kbd_code & KP_EVCODE_COL_MASK;
207                 row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT;
208                 code = MATRIX_SCAN_CODE(row_index, col_index,
209                                                 TC35893_KEYPAD_ROW_SHIFT);
210                 up = kbd_code & KP_RELEASE_EVT_MASK;
211 
212                 input_event(keypad->input, EV_MSC, MSC_SCAN, code);
213                 input_report_key(keypad->input, keypad->keymap[code], !up);
214                 input_sync(keypad->input);
215         }
216 
217         /* clear IRQ */
218         tc3589x_set_bits(tc3589x, TC3589x_KBDIC,
219                         0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR);
220         /* enable IRQ */
221         tc3589x_set_bits(tc3589x, TC3589x_KBDMSK,
222                         0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT);
223 
224         return IRQ_HANDLED;
225 }
226 
227 static int tc3589x_keypad_enable(struct tc_keypad *keypad)
228 {
229         struct tc3589x *tc3589x = keypad->tc3589x;
230         int ret;
231 
232         /* pull the keypad module out of reset */
233         ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x0);
234         if (ret < 0)
235                 return ret;
236 
237         /* configure KBDMFS */
238         ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMFS, 0x0, TC3589x_KBDMFS_EN);
239         if (ret < 0)
240                 return ret;
241 
242         /* enable the keypad clock */
243         ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x0, KPD_CLK_EN);
244         if (ret < 0)
245                 return ret;
246 
247         /* clear pending IRQs */
248         ret =  tc3589x_set_bits(tc3589x, TC3589x_RSTINTCLR, 0x0, 0x1);
249         if (ret < 0)
250                 return ret;
251 
252         /* enable the IRQs */
253         ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0,
254                                         TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT);
255         if (ret < 0)
256                 return ret;
257 
258         keypad->keypad_stopped = false;
259 
260         return ret;
261 }
262 
263 static int tc3589x_keypad_disable(struct tc_keypad *keypad)
264 {
265         struct tc3589x *tc3589x = keypad->tc3589x;
266         int ret;
267 
268         /* clear IRQ */
269         ret = tc3589x_set_bits(tc3589x, TC3589x_KBDIC,
270                         0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR);
271         if (ret < 0)
272                 return ret;
273 
274         /* disable all interrupts */
275         ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK,
276                         ~(TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT), 0x0);
277         if (ret < 0)
278                 return ret;
279 
280         /* disable the keypad module */
281         ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x1, 0x0);
282         if (ret < 0)
283                 return ret;
284 
285         /* put the keypad module into reset */
286         ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x1);
287 
288         keypad->keypad_stopped = true;
289 
290         return ret;
291 }
292 
293 static int tc3589x_keypad_open(struct input_dev *input)
294 {
295         int error;
296         struct tc_keypad *keypad = input_get_drvdata(input);
297 
298         /* enable the keypad module */
299         error = tc3589x_keypad_enable(keypad);
300         if (error < 0) {
301                 dev_err(&input->dev, "failed to enable keypad module\n");
302                 return error;
303         }
304 
305         error = tc3589x_keypad_init_key_hardware(keypad);
306         if (error < 0) {
307                 dev_err(&input->dev, "failed to configure keypad module\n");
308                 return error;
309         }
310 
311         return 0;
312 }
313 
314 static void tc3589x_keypad_close(struct input_dev *input)
315 {
316         struct tc_keypad *keypad = input_get_drvdata(input);
317 
318         /* disable the keypad module */
319         tc3589x_keypad_disable(keypad);
320 }
321 
322 static const struct tc3589x_keypad_platform_data *
323 tc3589x_keypad_of_probe(struct device *dev)
324 {
325         struct device_node *np = dev->of_node;
326         struct tc3589x_keypad_platform_data *plat;
327         u32 cols, rows;
328         u32 debounce_ms;
329         int proplen;
330 
331         if (!np)
332                 return ERR_PTR(-ENODEV);
333 
334         plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
335         if (!plat)
336                 return ERR_PTR(-ENOMEM);
337 
338         of_property_read_u32(np, "keypad,num-columns", &cols);
339         of_property_read_u32(np, "keypad,num-rows", &rows);
340         plat->kcol = (u8) cols;
341         plat->krow = (u8) rows;
342         if (!plat->krow || !plat->kcol ||
343              plat->krow > TC_KPD_ROWS || plat->kcol > TC_KPD_COLUMNS) {
344                 dev_err(dev,
345                         "keypad columns/rows not properly specified (%ux%u)\n",
346                         plat->kcol, plat->krow);
347                 return ERR_PTR(-EINVAL);
348         }
349 
350         if (!of_get_property(np, "linux,keymap", &proplen)) {
351                 dev_err(dev, "property linux,keymap not found\n");
352                 return ERR_PTR(-ENOENT);
353         }
354 
355         plat->no_autorepeat = of_property_read_bool(np, "linux,no-autorepeat");
356 
357         plat->enable_wakeup = of_property_read_bool(np, "wakeup-source") ||
358                               /* legacy name */
359                               of_property_read_bool(np, "linux,wakeup");
360 
361         /* The custom delay format is ms/16 */
362         of_property_read_u32(np, "debounce-delay-ms", &debounce_ms);
363         if (debounce_ms)
364                 plat->debounce_period = debounce_ms * 16;
365         else
366                 plat->debounce_period = TC_KPD_DEBOUNCE_PERIOD;
367 
368         plat->settle_time = TC_KPD_SETTLE_TIME;
369         /* FIXME: should be property of the IRQ resource? */
370         plat->irqtype = IRQF_TRIGGER_FALLING;
371 
372         return plat;
373 }
374 
375 static int tc3589x_keypad_probe(struct platform_device *pdev)
376 {
377         struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
378         struct tc_keypad *keypad;
379         struct input_dev *input;
380         const struct tc3589x_keypad_platform_data *plat;
381         int error, irq;
382 
383         plat = tc3589x_keypad_of_probe(&pdev->dev);
384         if (IS_ERR(plat)) {
385                 dev_err(&pdev->dev, "invalid keypad platform data\n");
386                 return PTR_ERR(plat);
387         }
388 
389         irq = platform_get_irq(pdev, 0);
390         if (irq < 0)
391                 return irq;
392 
393         keypad = devm_kzalloc(&pdev->dev, sizeof(struct tc_keypad),
394                               GFP_KERNEL);
395         if (!keypad)
396                 return -ENOMEM;
397 
398         input = devm_input_allocate_device(&pdev->dev);
399         if (!input) {
400                 dev_err(&pdev->dev, "failed to allocate input device\n");
401                 return -ENOMEM;
402         }
403 
404         keypad->board = plat;
405         keypad->input = input;
406         keypad->tc3589x = tc3589x;
407 
408         input->id.bustype = BUS_I2C;
409         input->name = pdev->name;
410         input->dev.parent = &pdev->dev;
411 
412         input->open = tc3589x_keypad_open;
413         input->close = tc3589x_keypad_close;
414 
415         error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
416                                            TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL,
417                                            NULL, input);
418         if (error) {
419                 dev_err(&pdev->dev, "Failed to build keymap\n");
420                 return error;
421         }
422 
423         keypad->keymap = input->keycode;
424 
425         input_set_capability(input, EV_MSC, MSC_SCAN);
426         if (!plat->no_autorepeat)
427                 __set_bit(EV_REP, input->evbit);
428 
429         input_set_drvdata(input, keypad);
430 
431         tc3589x_keypad_disable(keypad);
432 
433         error = devm_request_threaded_irq(&pdev->dev, irq,
434                                           NULL, tc3589x_keypad_irq,
435                                           plat->irqtype | IRQF_ONESHOT,
436                                           "tc3589x-keypad", keypad);
437         if (error) {
438                 dev_err(&pdev->dev,
439                                 "Could not allocate irq %d,error %d\n",
440                                 irq, error);
441                 return error;
442         }
443 
444         error = input_register_device(input);
445         if (error) {
446                 dev_err(&pdev->dev, "Could not register input device\n");
447                 return error;
448         }
449 
450         /* let platform decide if keypad is a wakeup source or not */
451         device_init_wakeup(&pdev->dev, plat->enable_wakeup);
452         device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup);
453 
454         platform_set_drvdata(pdev, keypad);
455 
456         return 0;
457 }
458 
459 #ifdef CONFIG_PM_SLEEP
460 static int tc3589x_keypad_suspend(struct device *dev)
461 {
462         struct platform_device *pdev = to_platform_device(dev);
463         struct tc_keypad *keypad = platform_get_drvdata(pdev);
464         int irq = platform_get_irq(pdev, 0);
465 
466         /* keypad is already off; we do nothing */
467         if (keypad->keypad_stopped)
468                 return 0;
469 
470         /* if device is not a wakeup source, disable it for powersave */
471         if (!device_may_wakeup(&pdev->dev))
472                 tc3589x_keypad_disable(keypad);
473         else
474                 enable_irq_wake(irq);
475 
476         return 0;
477 }
478 
479 static int tc3589x_keypad_resume(struct device *dev)
480 {
481         struct platform_device *pdev = to_platform_device(dev);
482         struct tc_keypad *keypad = platform_get_drvdata(pdev);
483         int irq = platform_get_irq(pdev, 0);
484 
485         if (!keypad->keypad_stopped)
486                 return 0;
487 
488         /* enable the device to resume normal operations */
489         if (!device_may_wakeup(&pdev->dev))
490                 tc3589x_keypad_enable(keypad);
491         else
492                 disable_irq_wake(irq);
493 
494         return 0;
495 }
496 #endif
497 
498 static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
499                          tc3589x_keypad_suspend, tc3589x_keypad_resume);
500 
501 static struct platform_driver tc3589x_keypad_driver = {
502         .driver = {
503                 .name   = "tc3589x-keypad",
504                 .pm     = &tc3589x_keypad_dev_pm_ops,
505         },
506         .probe  = tc3589x_keypad_probe,
507 };
508 module_platform_driver(tc3589x_keypad_driver);
509 
510 MODULE_LICENSE("GPL v2");
511 MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer");
512 MODULE_DESCRIPTION("TC35893 Keypad Driver");
513 MODULE_ALIAS("platform:tc3589x-keypad");
514 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us