linux/drivers/input/keyboard/imx_keypad.c
<<
>>
Prefs
   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
  44struct 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. */
  78static 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 */
 143static 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 */
 183static 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
 287static 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
 312static 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
 348static 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
 363static 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
 380static 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
 406open_err:
 407        imx_keypad_close(dev);
 408        return -EIO;
 409}
 410
 411#ifdef CONFIG_OF
 412static const struct of_device_id imx_keypad_of_match[] = {
 413        { .compatible = "fsl,imx21-kpp", },
 414        { /* sentinel */ }
 415};
 416MODULE_DEVICE_TABLE(of, imx_keypad_of_match);
 417#endif
 418
 419static 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        struct resource *res;
 426        int irq, error, i, row, col;
 427
 428        if (!keymap_data && !pdev->dev.of_node) {
 429                dev_err(&pdev->dev, "no keymap defined\n");
 430                return -EINVAL;
 431        }
 432
 433        irq = platform_get_irq(pdev, 0);
 434        if (irq < 0) {
 435                dev_err(&pdev->dev, "no irq defined in platform data\n");
 436                return irq;
 437        }
 438
 439        input_dev = devm_input_allocate_device(&pdev->dev);
 440        if (!input_dev) {
 441                dev_err(&pdev->dev, "failed to allocate the input device\n");
 442                return -ENOMEM;
 443        }
 444
 445        keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
 446        if (!keypad) {
 447                dev_err(&pdev->dev, "not enough memory for driver data\n");
 448                return -ENOMEM;
 449        }
 450
 451        keypad->input_dev = input_dev;
 452        keypad->irq = irq;
 453        keypad->stable_count = 0;
 454
 455        timer_setup(&keypad->check_matrix_timer,
 456                    imx_keypad_check_for_events, 0);
 457
 458        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 459        keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res);
 460        if (IS_ERR(keypad->mmio_base))
 461                return PTR_ERR(keypad->mmio_base);
 462
 463        keypad->clk = devm_clk_get(&pdev->dev, NULL);
 464        if (IS_ERR(keypad->clk)) {
 465                dev_err(&pdev->dev, "failed to get keypad clock\n");
 466                return PTR_ERR(keypad->clk);
 467        }
 468
 469        /* Init the Input device */
 470        input_dev->name = pdev->name;
 471        input_dev->id.bustype = BUS_HOST;
 472        input_dev->dev.parent = &pdev->dev;
 473        input_dev->open = imx_keypad_open;
 474        input_dev->close = imx_keypad_close;
 475
 476        error = matrix_keypad_build_keymap(keymap_data, NULL,
 477                                           MAX_MATRIX_KEY_ROWS,
 478                                           MAX_MATRIX_KEY_COLS,
 479                                           keypad->keycodes, input_dev);
 480        if (error) {
 481                dev_err(&pdev->dev, "failed to build keymap\n");
 482                return error;
 483        }
 484
 485        /* Search for rows and cols enabled */
 486        for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
 487                for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
 488                        i = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
 489                        if (keypad->keycodes[i] != KEY_RESERVED) {
 490                                keypad->rows_en_mask |= 1 << row;
 491                                keypad->cols_en_mask |= 1 << col;
 492                        }
 493                }
 494        }
 495        dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
 496        dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);
 497
 498        __set_bit(EV_REP, input_dev->evbit);
 499        input_set_capability(input_dev, EV_MSC, MSC_SCAN);
 500        input_set_drvdata(input_dev, keypad);
 501
 502        /* Ensure that the keypad will stay dormant until opened */
 503        error = clk_prepare_enable(keypad->clk);
 504        if (error)
 505                return error;
 506        imx_keypad_inhibit(keypad);
 507        clk_disable_unprepare(keypad->clk);
 508
 509        error = devm_request_irq(&pdev->dev, irq, imx_keypad_irq_handler, 0,
 510                            pdev->name, keypad);
 511        if (error) {
 512                dev_err(&pdev->dev, "failed to request IRQ\n");
 513                return error;
 514        }
 515
 516        /* Register the input device */
 517        error = input_register_device(input_dev);
 518        if (error) {
 519                dev_err(&pdev->dev, "failed to register input device\n");
 520                return error;
 521        }
 522
 523        platform_set_drvdata(pdev, keypad);
 524        device_init_wakeup(&pdev->dev, 1);
 525
 526        return 0;
 527}
 528
 529static int __maybe_unused imx_kbd_suspend(struct device *dev)
 530{
 531        struct platform_device *pdev = to_platform_device(dev);
 532        struct imx_keypad *kbd = platform_get_drvdata(pdev);
 533        struct input_dev *input_dev = kbd->input_dev;
 534
 535        /* imx kbd can wake up system even clock is disabled */
 536        mutex_lock(&input_dev->mutex);
 537
 538        if (input_dev->users)
 539                clk_disable_unprepare(kbd->clk);
 540
 541        mutex_unlock(&input_dev->mutex);
 542
 543        if (device_may_wakeup(&pdev->dev))
 544                enable_irq_wake(kbd->irq);
 545
 546        return 0;
 547}
 548
 549static int __maybe_unused imx_kbd_resume(struct device *dev)
 550{
 551        struct platform_device *pdev = to_platform_device(dev);
 552        struct imx_keypad *kbd = platform_get_drvdata(pdev);
 553        struct input_dev *input_dev = kbd->input_dev;
 554        int ret = 0;
 555
 556        if (device_may_wakeup(&pdev->dev))
 557                disable_irq_wake(kbd->irq);
 558
 559        mutex_lock(&input_dev->mutex);
 560
 561        if (input_dev->users) {
 562                ret = clk_prepare_enable(kbd->clk);
 563                if (ret)
 564                        goto err_clk;
 565        }
 566
 567err_clk:
 568        mutex_unlock(&input_dev->mutex);
 569
 570        return ret;
 571}
 572
 573static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
 574
 575static struct platform_driver imx_keypad_driver = {
 576        .driver         = {
 577                .name   = "imx-keypad",
 578                .pm     = &imx_kbd_pm_ops,
 579                .of_match_table = of_match_ptr(imx_keypad_of_match),
 580        },
 581        .probe          = imx_keypad_probe,
 582};
 583module_platform_driver(imx_keypad_driver);
 584
 585MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
 586MODULE_DESCRIPTION("IMX Keypad Port Driver");
 587MODULE_LICENSE("GPL v2");
 588MODULE_ALIAS("platform:imx-keypad");
 589