root/drivers/input/keyboard/imx_keypad.c

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

DEFINITIONS

This source file includes following definitions.
  1. imx_keypad_scan_matrix
  2. imx_keypad_fire_events
  3. imx_keypad_check_for_events
  4. imx_keypad_irq_handler
  5. imx_keypad_config
  6. imx_keypad_inhibit
  7. imx_keypad_close
  8. imx_keypad_open
  9. imx_keypad_probe
  10. imx_kbd_noirq_suspend
  11. imx_kbd_noirq_resume

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // Driver for the IMX keypad port.
   4 // Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
   5 
   6 #include <linux/clk.h>
   7 #include <linux/delay.h>
   8 #include <linux/device.h>
   9 #include <linux/err.h>
  10 #include <linux/input/matrix_keypad.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/io.h>
  13 #include <linux/jiffies.h>
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/of.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/slab.h>
  19 #include <linux/timer.h>
  20 
  21 /*
  22  * Keypad Controller registers (halfword)
  23  */
  24 #define KPCR            0x00 /* Keypad Control Register */
  25 
  26 #define KPSR            0x02 /* Keypad Status Register */
  27 #define KBD_STAT_KPKD   (0x1 << 0) /* Key Press Interrupt Status bit (w1c) */
  28 #define KBD_STAT_KPKR   (0x1 << 1) /* Key Release Interrupt Status bit (w1c) */
  29 #define KBD_STAT_KDSC   (0x1 << 2) /* Key Depress Synch Chain Status bit (w1c)*/
  30 #define KBD_STAT_KRSS   (0x1 << 3) /* Key Release Synch Status bit (w1c)*/
  31 #define KBD_STAT_KDIE   (0x1 << 8) /* Key Depress Interrupt Enable Status bit */
  32 #define KBD_STAT_KRIE   (0x1 << 9) /* Key Release Interrupt Enable */
  33 #define KBD_STAT_KPPEN  (0x1 << 10) /* Keypad Clock Enable */
  34 
  35 #define KDDR            0x04 /* Keypad Data Direction Register */
  36 #define KPDR            0x06 /* Keypad Data Register */
  37 
  38 #define MAX_MATRIX_KEY_ROWS     8
  39 #define MAX_MATRIX_KEY_COLS     8
  40 #define MATRIX_ROW_SHIFT        3
  41 
  42 #define MAX_MATRIX_KEY_NUM      (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
  43 
  44 struct imx_keypad {
  45 
  46         struct clk *clk;
  47         struct input_dev *input_dev;
  48         void __iomem *mmio_base;
  49 
  50         int                     irq;
  51         struct timer_list       check_matrix_timer;
  52 
  53         /*
  54          * The matrix is stable only if no changes are detected after
  55          * IMX_KEYPAD_SCANS_FOR_STABILITY scans
  56          */
  57 #define IMX_KEYPAD_SCANS_FOR_STABILITY 3
  58         int                     stable_count;
  59 
  60         bool                    enabled;
  61 
  62         /* Masks for enabled rows/cols */
  63         unsigned short          rows_en_mask;
  64         unsigned short          cols_en_mask;
  65 
  66         unsigned short          keycodes[MAX_MATRIX_KEY_NUM];
  67 
  68         /*
  69          * Matrix states:
  70          * -stable: achieved after a complete debounce process.
  71          * -unstable: used in the debouncing process.
  72          */
  73         unsigned short          matrix_stable_state[MAX_MATRIX_KEY_COLS];
  74         unsigned short          matrix_unstable_state[MAX_MATRIX_KEY_COLS];
  75 };
  76 
  77 /* Scan the matrix and return the new state in *matrix_volatile_state. */
  78 static void imx_keypad_scan_matrix(struct imx_keypad *keypad,
  79                                   unsigned short *matrix_volatile_state)
  80 {
  81         int col;
  82         unsigned short reg_val;
  83 
  84         for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
  85                 if ((keypad->cols_en_mask & (1 << col)) == 0)
  86                         continue;
  87                 /*
  88                  * Discharge keypad capacitance:
  89                  * 2. write 1s on column data.
  90                  * 3. configure columns as totem-pole to discharge capacitance.
  91                  * 4. configure columns as open-drain.
  92                  */
  93                 reg_val = readw(keypad->mmio_base + KPDR);
  94                 reg_val |= 0xff00;
  95                 writew(reg_val, keypad->mmio_base + KPDR);
  96 
  97                 reg_val = readw(keypad->mmio_base + KPCR);
  98                 reg_val &= ~((keypad->cols_en_mask & 0xff) << 8);
  99                 writew(reg_val, keypad->mmio_base + KPCR);
 100 
 101                 udelay(2);
 102 
 103                 reg_val = readw(keypad->mmio_base + KPCR);
 104                 reg_val |= (keypad->cols_en_mask & 0xff) << 8;
 105                 writew(reg_val, keypad->mmio_base + KPCR);
 106 
 107                 /*
 108                  * 5. Write a single column to 0, others to 1.
 109                  * 6. Sample row inputs and save data.
 110                  * 7. Repeat steps 2 - 6 for remaining columns.
 111                  */
 112                 reg_val = readw(keypad->mmio_base + KPDR);
 113                 reg_val &= ~(1 << (8 + col));
 114                 writew(reg_val, keypad->mmio_base + KPDR);
 115 
 116                 /*
 117                  * Delay added to avoid propagating the 0 from column to row
 118                  * when scanning.
 119                  */
 120                 udelay(5);
 121 
 122                 /*
 123                  * 1s in matrix_volatile_state[col] means key pressures
 124                  * throw data from non enabled rows.
 125                  */
 126                 reg_val = readw(keypad->mmio_base + KPDR);
 127                 matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask;
 128         }
 129 
 130         /*
 131          * Return in standby mode:
 132          * 9. write 0s to columns
 133          */
 134         reg_val = readw(keypad->mmio_base + KPDR);
 135         reg_val &= 0x00ff;
 136         writew(reg_val, keypad->mmio_base + KPDR);
 137 }
 138 
 139 /*
 140  * Compare the new matrix state (volatile) with the stable one stored in
 141  * keypad->matrix_stable_state and fire events if changes are detected.
 142  */
 143 static void imx_keypad_fire_events(struct imx_keypad *keypad,
 144                                    unsigned short *matrix_volatile_state)
 145 {
 146         struct input_dev *input_dev = keypad->input_dev;
 147         int row, col;
 148 
 149         for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
 150                 unsigned short bits_changed;
 151                 int code;
 152 
 153                 if ((keypad->cols_en_mask & (1 << col)) == 0)
 154                         continue; /* Column is not enabled */
 155 
 156                 bits_changed = keypad->matrix_stable_state[col] ^
 157                                                 matrix_volatile_state[col];
 158 
 159                 if (bits_changed == 0)
 160                         continue; /* Column does not contain changes */
 161 
 162                 for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
 163                         if ((keypad->rows_en_mask & (1 << row)) == 0)
 164                                 continue; /* Row is not enabled */
 165                         if ((bits_changed & (1 << row)) == 0)
 166                                 continue; /* Row does not contain changes */
 167 
 168                         code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
 169                         input_event(input_dev, EV_MSC, MSC_SCAN, code);
 170                         input_report_key(input_dev, keypad->keycodes[code],
 171                                 matrix_volatile_state[col] & (1 << row));
 172                         dev_dbg(&input_dev->dev, "Event code: %d, val: %d",
 173                                 keypad->keycodes[code],
 174                                 matrix_volatile_state[col] & (1 << row));
 175                 }
 176         }
 177         input_sync(input_dev);
 178 }
 179 
 180 /*
 181  * imx_keypad_check_for_events is the timer handler.
 182  */
 183 static void imx_keypad_check_for_events(struct timer_list *t)
 184 {
 185         struct imx_keypad *keypad = from_timer(keypad, t, check_matrix_timer);
 186         unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS];
 187         unsigned short reg_val;
 188         bool state_changed, is_zero_matrix;
 189         int i;
 190 
 191         memset(matrix_volatile_state, 0, sizeof(matrix_volatile_state));
 192 
 193         imx_keypad_scan_matrix(keypad, matrix_volatile_state);
 194 
 195         state_changed = false;
 196         for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
 197                 if ((keypad->cols_en_mask & (1 << i)) == 0)
 198                         continue;
 199 
 200                 if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) {
 201                         state_changed = true;
 202                         break;
 203                 }
 204         }
 205 
 206         /*
 207          * If the matrix state is changed from the previous scan
 208          *   (Re)Begin the debouncing process, saving the new state in
 209          *    keypad->matrix_unstable_state.
 210          * else
 211          *   Increase the count of number of scans with a stable state.
 212          */
 213         if (state_changed) {
 214                 memcpy(keypad->matrix_unstable_state, matrix_volatile_state,
 215                         sizeof(matrix_volatile_state));
 216                 keypad->stable_count = 0;
 217         } else
 218                 keypad->stable_count++;
 219 
 220         /*
 221          * If the matrix is not as stable as we want reschedule scan
 222          * in the near future.
 223          */
 224         if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) {
 225                 mod_timer(&keypad->check_matrix_timer,
 226                           jiffies + msecs_to_jiffies(10));
 227                 return;
 228         }
 229 
 230         /*
 231          * If the matrix state is stable, fire the events and save the new
 232          * stable state. Note, if the matrix is kept stable for longer
 233          * (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all
 234          * events have already been generated.
 235          */
 236         if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) {
 237                 imx_keypad_fire_events(keypad, matrix_volatile_state);
 238 
 239                 memcpy(keypad->matrix_stable_state, matrix_volatile_state,
 240                         sizeof(matrix_volatile_state));
 241         }
 242 
 243         is_zero_matrix = true;
 244         for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
 245                 if (matrix_volatile_state[i] != 0) {
 246                         is_zero_matrix = false;
 247                         break;
 248                 }
 249         }
 250 
 251 
 252         if (is_zero_matrix) {
 253                 /*
 254                  * All keys have been released. Enable only the KDI
 255                  * interrupt for future key presses (clear the KDI
 256                  * status bit and its sync chain before that).
 257                  */
 258                 reg_val = readw(keypad->mmio_base + KPSR);
 259                 reg_val |= KBD_STAT_KPKD | KBD_STAT_KDSC;
 260                 writew(reg_val, keypad->mmio_base + KPSR);
 261 
 262                 reg_val = readw(keypad->mmio_base + KPSR);
 263                 reg_val |= KBD_STAT_KDIE;
 264                 reg_val &= ~KBD_STAT_KRIE;
 265                 writew(reg_val, keypad->mmio_base + KPSR);
 266         } else {
 267                 /*
 268                  * Some keys are still pressed. Schedule a rescan in
 269                  * attempt to detect multiple key presses and enable
 270                  * the KRI interrupt to react quickly to key release
 271                  * event.
 272                  */
 273                 mod_timer(&keypad->check_matrix_timer,
 274                           jiffies + msecs_to_jiffies(60));
 275 
 276                 reg_val = readw(keypad->mmio_base + KPSR);
 277                 reg_val |= KBD_STAT_KPKR | KBD_STAT_KRSS;
 278                 writew(reg_val, keypad->mmio_base + KPSR);
 279 
 280                 reg_val = readw(keypad->mmio_base + KPSR);
 281                 reg_val |= KBD_STAT_KRIE;
 282                 reg_val &= ~KBD_STAT_KDIE;
 283                 writew(reg_val, keypad->mmio_base + KPSR);
 284         }
 285 }
 286 
 287 static irqreturn_t imx_keypad_irq_handler(int irq, void *dev_id)
 288 {
 289         struct imx_keypad *keypad = dev_id;
 290         unsigned short reg_val;
 291 
 292         reg_val = readw(keypad->mmio_base + KPSR);
 293 
 294         /* Disable both interrupt types */
 295         reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
 296         /* Clear interrupts status bits */
 297         reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
 298         writew(reg_val, keypad->mmio_base + KPSR);
 299 
 300         if (keypad->enabled) {
 301                 /* The matrix is supposed to be changed */
 302                 keypad->stable_count = 0;
 303 
 304                 /* Schedule the scanning procedure near in the future */
 305                 mod_timer(&keypad->check_matrix_timer,
 306                           jiffies + msecs_to_jiffies(2));
 307         }
 308 
 309         return IRQ_HANDLED;
 310 }
 311 
 312 static void imx_keypad_config(struct imx_keypad *keypad)
 313 {
 314         unsigned short reg_val;
 315 
 316         /*
 317          * Include enabled rows in interrupt generation (KPCR[7:0])
 318          * Configure keypad columns as open-drain (KPCR[15:8])
 319          */
 320         reg_val = readw(keypad->mmio_base + KPCR);
 321         reg_val |= keypad->rows_en_mask & 0xff;         /* rows */
 322         reg_val |= (keypad->cols_en_mask & 0xff) << 8;  /* cols */
 323         writew(reg_val, keypad->mmio_base + KPCR);
 324 
 325         /* Write 0's to KPDR[15:8] (Colums) */
 326         reg_val = readw(keypad->mmio_base + KPDR);
 327         reg_val &= 0x00ff;
 328         writew(reg_val, keypad->mmio_base + KPDR);
 329 
 330         /* Configure columns as output, rows as input (KDDR[15:0]) */
 331         writew(0xff00, keypad->mmio_base + KDDR);
 332 
 333         /*
 334          * Clear Key Depress and Key Release status bit.
 335          * Clear both synchronizer chain.
 336          */
 337         reg_val = readw(keypad->mmio_base + KPSR);
 338         reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD |
 339                    KBD_STAT_KDSC | KBD_STAT_KRSS;
 340         writew(reg_val, keypad->mmio_base + KPSR);
 341 
 342         /* Enable KDI and disable KRI (avoid false release events). */
 343         reg_val |= KBD_STAT_KDIE;
 344         reg_val &= ~KBD_STAT_KRIE;
 345         writew(reg_val, keypad->mmio_base + KPSR);
 346 }
 347 
 348 static void imx_keypad_inhibit(struct imx_keypad *keypad)
 349 {
 350         unsigned short reg_val;
 351 
 352         /* Inhibit KDI and KRI interrupts. */
 353         reg_val = readw(keypad->mmio_base + KPSR);
 354         reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
 355         reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
 356         writew(reg_val, keypad->mmio_base + KPSR);
 357 
 358         /* Colums as open drain and disable all rows */
 359         reg_val = (keypad->cols_en_mask & 0xff) << 8;
 360         writew(reg_val, keypad->mmio_base + KPCR);
 361 }
 362 
 363 static void imx_keypad_close(struct input_dev *dev)
 364 {
 365         struct imx_keypad *keypad = input_get_drvdata(dev);
 366 
 367         dev_dbg(&dev->dev, ">%s\n", __func__);
 368 
 369         /* Mark keypad as being inactive */
 370         keypad->enabled = false;
 371         synchronize_irq(keypad->irq);
 372         del_timer_sync(&keypad->check_matrix_timer);
 373 
 374         imx_keypad_inhibit(keypad);
 375 
 376         /* Disable clock unit */
 377         clk_disable_unprepare(keypad->clk);
 378 }
 379 
 380 static int imx_keypad_open(struct input_dev *dev)
 381 {
 382         struct imx_keypad *keypad = input_get_drvdata(dev);
 383         int error;
 384 
 385         dev_dbg(&dev->dev, ">%s\n", __func__);
 386 
 387         /* Enable the kpp clock */
 388         error = clk_prepare_enable(keypad->clk);
 389         if (error)
 390                 return error;
 391 
 392         /* We became active from now */
 393         keypad->enabled = true;
 394 
 395         imx_keypad_config(keypad);
 396 
 397         /* Sanity control, not all the rows must be actived now. */
 398         if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) {
 399                 dev_err(&dev->dev,
 400                         "too many keys pressed, control pins initialisation\n");
 401                 goto open_err;
 402         }
 403 
 404         return 0;
 405 
 406 open_err:
 407         imx_keypad_close(dev);
 408         return -EIO;
 409 }
 410 
 411 #ifdef CONFIG_OF
 412 static const struct of_device_id imx_keypad_of_match[] = {
 413         { .compatible = "fsl,imx21-kpp", },
 414         { /* sentinel */ }
 415 };
 416 MODULE_DEVICE_TABLE(of, imx_keypad_of_match);
 417 #endif
 418 
 419 static int imx_keypad_probe(struct platform_device *pdev)
 420 {
 421         const struct matrix_keymap_data *keymap_data =
 422                         dev_get_platdata(&pdev->dev);
 423         struct imx_keypad *keypad;
 424         struct input_dev *input_dev;
 425         int irq, error, i, row, col;
 426 
 427         if (!keymap_data && !pdev->dev.of_node) {
 428                 dev_err(&pdev->dev, "no keymap defined\n");
 429                 return -EINVAL;
 430         }
 431 
 432         irq = platform_get_irq(pdev, 0);
 433         if (irq < 0)
 434                 return irq;
 435 
 436         input_dev = devm_input_allocate_device(&pdev->dev);
 437         if (!input_dev) {
 438                 dev_err(&pdev->dev, "failed to allocate the input device\n");
 439                 return -ENOMEM;
 440         }
 441 
 442         keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
 443         if (!keypad) {
 444                 dev_err(&pdev->dev, "not enough memory for driver data\n");
 445                 return -ENOMEM;
 446         }
 447 
 448         keypad->input_dev = input_dev;
 449         keypad->irq = irq;
 450         keypad->stable_count = 0;
 451 
 452         timer_setup(&keypad->check_matrix_timer,
 453                     imx_keypad_check_for_events, 0);
 454 
 455         keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0);
 456         if (IS_ERR(keypad->mmio_base))
 457                 return PTR_ERR(keypad->mmio_base);
 458 
 459         keypad->clk = devm_clk_get(&pdev->dev, NULL);
 460         if (IS_ERR(keypad->clk)) {
 461                 dev_err(&pdev->dev, "failed to get keypad clock\n");
 462                 return PTR_ERR(keypad->clk);
 463         }
 464 
 465         /* Init the Input device */
 466         input_dev->name = pdev->name;
 467         input_dev->id.bustype = BUS_HOST;
 468         input_dev->dev.parent = &pdev->dev;
 469         input_dev->open = imx_keypad_open;
 470         input_dev->close = imx_keypad_close;
 471 
 472         error = matrix_keypad_build_keymap(keymap_data, NULL,
 473                                            MAX_MATRIX_KEY_ROWS,
 474                                            MAX_MATRIX_KEY_COLS,
 475                                            keypad->keycodes, input_dev);
 476         if (error) {
 477                 dev_err(&pdev->dev, "failed to build keymap\n");
 478                 return error;
 479         }
 480 
 481         /* Search for rows and cols enabled */
 482         for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
 483                 for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
 484                         i = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
 485                         if (keypad->keycodes[i] != KEY_RESERVED) {
 486                                 keypad->rows_en_mask |= 1 << row;
 487                                 keypad->cols_en_mask |= 1 << col;
 488                         }
 489                 }
 490         }
 491         dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
 492         dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);
 493 
 494         __set_bit(EV_REP, input_dev->evbit);
 495         input_set_capability(input_dev, EV_MSC, MSC_SCAN);
 496         input_set_drvdata(input_dev, keypad);
 497 
 498         /* Ensure that the keypad will stay dormant until opened */
 499         error = clk_prepare_enable(keypad->clk);
 500         if (error)
 501                 return error;
 502         imx_keypad_inhibit(keypad);
 503         clk_disable_unprepare(keypad->clk);
 504 
 505         error = devm_request_irq(&pdev->dev, irq, imx_keypad_irq_handler, 0,
 506                             pdev->name, keypad);
 507         if (error) {
 508                 dev_err(&pdev->dev, "failed to request IRQ\n");
 509                 return error;
 510         }
 511 
 512         /* Register the input device */
 513         error = input_register_device(input_dev);
 514         if (error) {
 515                 dev_err(&pdev->dev, "failed to register input device\n");
 516                 return error;
 517         }
 518 
 519         platform_set_drvdata(pdev, keypad);
 520         device_init_wakeup(&pdev->dev, 1);
 521 
 522         return 0;
 523 }
 524 
 525 static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
 526 {
 527         struct platform_device *pdev = to_platform_device(dev);
 528         struct imx_keypad *kbd = platform_get_drvdata(pdev);
 529         struct input_dev *input_dev = kbd->input_dev;
 530         unsigned short reg_val = readw(kbd->mmio_base + KPSR);
 531 
 532         /* imx kbd can wake up system even clock is disabled */
 533         mutex_lock(&input_dev->mutex);
 534 
 535         if (input_dev->users)
 536                 clk_disable_unprepare(kbd->clk);
 537 
 538         mutex_unlock(&input_dev->mutex);
 539 
 540         if (device_may_wakeup(&pdev->dev)) {
 541                 if (reg_val & KBD_STAT_KPKD)
 542                         reg_val |= KBD_STAT_KRIE;
 543                 if (reg_val & KBD_STAT_KPKR)
 544                         reg_val |= KBD_STAT_KDIE;
 545                 writew(reg_val, kbd->mmio_base + KPSR);
 546 
 547                 enable_irq_wake(kbd->irq);
 548         }
 549 
 550         return 0;
 551 }
 552 
 553 static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
 554 {
 555         struct platform_device *pdev = to_platform_device(dev);
 556         struct imx_keypad *kbd = platform_get_drvdata(pdev);
 557         struct input_dev *input_dev = kbd->input_dev;
 558         int ret = 0;
 559 
 560         if (device_may_wakeup(&pdev->dev))
 561                 disable_irq_wake(kbd->irq);
 562 
 563         mutex_lock(&input_dev->mutex);
 564 
 565         if (input_dev->users) {
 566                 ret = clk_prepare_enable(kbd->clk);
 567                 if (ret)
 568                         goto err_clk;
 569         }
 570 
 571 err_clk:
 572         mutex_unlock(&input_dev->mutex);
 573 
 574         return ret;
 575 }
 576 
 577 static const struct dev_pm_ops imx_kbd_pm_ops = {
 578         SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_kbd_noirq_suspend, imx_kbd_noirq_resume)
 579 };
 580 
 581 static struct platform_driver imx_keypad_driver = {
 582         .driver         = {
 583                 .name   = "imx-keypad",
 584                 .pm     = &imx_kbd_pm_ops,
 585                 .of_match_table = of_match_ptr(imx_keypad_of_match),
 586         },
 587         .probe          = imx_keypad_probe,
 588 };
 589 module_platform_driver(imx_keypad_driver);
 590 
 591 MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
 592 MODULE_DESCRIPTION("IMX Keypad Port Driver");
 593 MODULE_LICENSE("GPL v2");
 594 MODULE_ALIAS("platform:imx-keypad");

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