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