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

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tc3589x_keypad_init_key_hardware
  2. tc3589x_keypad_irq
  3. tc3589x_keypad_enable
  4. tc3589x_keypad_disable
  5. tc3589x_keypad_open
  6. tc3589x_keypad_close
  7. tc3589x_keypad_of_probe
  8. tc3589x_keypad_probe
  9. tc3589x_keypad_suspend
  10. tc3589x_keypad_resume

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

/* [<][>][^][v][top][bottom][index][help] */