Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Driver for the IMX keypad port.
0004 // Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
0005 
0006 #include <linux/clk.h>
0007 #include <linux/delay.h>
0008 #include <linux/device.h>
0009 #include <linux/err.h>
0010 #include <linux/input/matrix_keypad.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/io.h>
0013 #include <linux/jiffies.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/slab.h>
0019 #include <linux/timer.h>
0020 
0021 /*
0022  * Keypad Controller registers (halfword)
0023  */
0024 #define KPCR        0x00 /* Keypad Control Register */
0025 
0026 #define KPSR        0x02 /* Keypad Status Register */
0027 #define KBD_STAT_KPKD   (0x1 << 0) /* Key Press Interrupt Status bit (w1c) */
0028 #define KBD_STAT_KPKR   (0x1 << 1) /* Key Release Interrupt Status bit (w1c) */
0029 #define KBD_STAT_KDSC   (0x1 << 2) /* Key Depress Synch Chain Status bit (w1c)*/
0030 #define KBD_STAT_KRSS   (0x1 << 3) /* Key Release Synch Status bit (w1c)*/
0031 #define KBD_STAT_KDIE   (0x1 << 8) /* Key Depress Interrupt Enable Status bit */
0032 #define KBD_STAT_KRIE   (0x1 << 9) /* Key Release Interrupt Enable */
0033 #define KBD_STAT_KPPEN  (0x1 << 10) /* Keypad Clock Enable */
0034 
0035 #define KDDR        0x04 /* Keypad Data Direction Register */
0036 #define KPDR        0x06 /* Keypad Data Register */
0037 
0038 #define MAX_MATRIX_KEY_ROWS 8
0039 #define MAX_MATRIX_KEY_COLS 8
0040 #define MATRIX_ROW_SHIFT    3
0041 
0042 #define MAX_MATRIX_KEY_NUM  (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
0043 
0044 struct imx_keypad {
0045 
0046     struct clk *clk;
0047     struct input_dev *input_dev;
0048     void __iomem *mmio_base;
0049 
0050     int         irq;
0051     struct timer_list   check_matrix_timer;
0052 
0053     /*
0054      * The matrix is stable only if no changes are detected after
0055      * IMX_KEYPAD_SCANS_FOR_STABILITY scans
0056      */
0057 #define IMX_KEYPAD_SCANS_FOR_STABILITY 3
0058     int         stable_count;
0059 
0060     bool            enabled;
0061 
0062     /* Masks for enabled rows/cols */
0063     unsigned short      rows_en_mask;
0064     unsigned short      cols_en_mask;
0065 
0066     unsigned short      keycodes[MAX_MATRIX_KEY_NUM];
0067 
0068     /*
0069      * Matrix states:
0070      * -stable: achieved after a complete debounce process.
0071      * -unstable: used in the debouncing process.
0072      */
0073     unsigned short      matrix_stable_state[MAX_MATRIX_KEY_COLS];
0074     unsigned short      matrix_unstable_state[MAX_MATRIX_KEY_COLS];
0075 };
0076 
0077 /* Scan the matrix and return the new state in *matrix_volatile_state. */
0078 static void imx_keypad_scan_matrix(struct imx_keypad *keypad,
0079                   unsigned short *matrix_volatile_state)
0080 {
0081     int col;
0082     unsigned short reg_val;
0083 
0084     for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
0085         if ((keypad->cols_en_mask & (1 << col)) == 0)
0086             continue;
0087         /*
0088          * Discharge keypad capacitance:
0089          * 2. write 1s on column data.
0090          * 3. configure columns as totem-pole to discharge capacitance.
0091          * 4. configure columns as open-drain.
0092          */
0093         reg_val = readw(keypad->mmio_base + KPDR);
0094         reg_val |= 0xff00;
0095         writew(reg_val, keypad->mmio_base + KPDR);
0096 
0097         reg_val = readw(keypad->mmio_base + KPCR);
0098         reg_val &= ~((keypad->cols_en_mask & 0xff) << 8);
0099         writew(reg_val, keypad->mmio_base + KPCR);
0100 
0101         udelay(2);
0102 
0103         reg_val = readw(keypad->mmio_base + KPCR);
0104         reg_val |= (keypad->cols_en_mask & 0xff) << 8;
0105         writew(reg_val, keypad->mmio_base + KPCR);
0106 
0107         /*
0108          * 5. Write a single column to 0, others to 1.
0109          * 6. Sample row inputs and save data.
0110          * 7. Repeat steps 2 - 6 for remaining columns.
0111          */
0112         reg_val = readw(keypad->mmio_base + KPDR);
0113         reg_val &= ~(1 << (8 + col));
0114         writew(reg_val, keypad->mmio_base + KPDR);
0115 
0116         /*
0117          * Delay added to avoid propagating the 0 from column to row
0118          * when scanning.
0119          */
0120         udelay(5);
0121 
0122         /*
0123          * 1s in matrix_volatile_state[col] means key pressures
0124          * throw data from non enabled rows.
0125          */
0126         reg_val = readw(keypad->mmio_base + KPDR);
0127         matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask;
0128     }
0129 
0130     /*
0131      * Return in standby mode:
0132      * 9. write 0s to columns
0133      */
0134     reg_val = readw(keypad->mmio_base + KPDR);
0135     reg_val &= 0x00ff;
0136     writew(reg_val, keypad->mmio_base + KPDR);
0137 }
0138 
0139 /*
0140  * Compare the new matrix state (volatile) with the stable one stored in
0141  * keypad->matrix_stable_state and fire events if changes are detected.
0142  */
0143 static void imx_keypad_fire_events(struct imx_keypad *keypad,
0144                    unsigned short *matrix_volatile_state)
0145 {
0146     struct input_dev *input_dev = keypad->input_dev;
0147     int row, col;
0148 
0149     for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
0150         unsigned short bits_changed;
0151         int code;
0152 
0153         if ((keypad->cols_en_mask & (1 << col)) == 0)
0154             continue; /* Column is not enabled */
0155 
0156         bits_changed = keypad->matrix_stable_state[col] ^
0157                         matrix_volatile_state[col];
0158 
0159         if (bits_changed == 0)
0160             continue; /* Column does not contain changes */
0161 
0162         for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
0163             if ((keypad->rows_en_mask & (1 << row)) == 0)
0164                 continue; /* Row is not enabled */
0165             if ((bits_changed & (1 << row)) == 0)
0166                 continue; /* Row does not contain changes */
0167 
0168             code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
0169             input_event(input_dev, EV_MSC, MSC_SCAN, code);
0170             input_report_key(input_dev, keypad->keycodes[code],
0171                 matrix_volatile_state[col] & (1 << row));
0172             dev_dbg(&input_dev->dev, "Event code: %d, val: %d",
0173                 keypad->keycodes[code],
0174                 matrix_volatile_state[col] & (1 << row));
0175         }
0176     }
0177     input_sync(input_dev);
0178 }
0179 
0180 /*
0181  * imx_keypad_check_for_events is the timer handler.
0182  */
0183 static void imx_keypad_check_for_events(struct timer_list *t)
0184 {
0185     struct imx_keypad *keypad = from_timer(keypad, t, check_matrix_timer);
0186     unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS];
0187     unsigned short reg_val;
0188     bool state_changed, is_zero_matrix;
0189     int i;
0190 
0191     memset(matrix_volatile_state, 0, sizeof(matrix_volatile_state));
0192 
0193     imx_keypad_scan_matrix(keypad, matrix_volatile_state);
0194 
0195     state_changed = false;
0196     for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
0197         if ((keypad->cols_en_mask & (1 << i)) == 0)
0198             continue;
0199 
0200         if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) {
0201             state_changed = true;
0202             break;
0203         }
0204     }
0205 
0206     /*
0207      * If the matrix state is changed from the previous scan
0208      *   (Re)Begin the debouncing process, saving the new state in
0209      *    keypad->matrix_unstable_state.
0210      * else
0211      *   Increase the count of number of scans with a stable state.
0212      */
0213     if (state_changed) {
0214         memcpy(keypad->matrix_unstable_state, matrix_volatile_state,
0215             sizeof(matrix_volatile_state));
0216         keypad->stable_count = 0;
0217     } else
0218         keypad->stable_count++;
0219 
0220     /*
0221      * If the matrix is not as stable as we want reschedule scan
0222      * in the near future.
0223      */
0224     if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) {
0225         mod_timer(&keypad->check_matrix_timer,
0226               jiffies + msecs_to_jiffies(10));
0227         return;
0228     }
0229 
0230     /*
0231      * If the matrix state is stable, fire the events and save the new
0232      * stable state. Note, if the matrix is kept stable for longer
0233      * (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all
0234      * events have already been generated.
0235      */
0236     if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) {
0237         imx_keypad_fire_events(keypad, matrix_volatile_state);
0238 
0239         memcpy(keypad->matrix_stable_state, matrix_volatile_state,
0240             sizeof(matrix_volatile_state));
0241     }
0242 
0243     is_zero_matrix = true;
0244     for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
0245         if (matrix_volatile_state[i] != 0) {
0246             is_zero_matrix = false;
0247             break;
0248         }
0249     }
0250 
0251 
0252     if (is_zero_matrix) {
0253         /*
0254          * All keys have been released. Enable only the KDI
0255          * interrupt for future key presses (clear the KDI
0256          * status bit and its sync chain before that).
0257          */
0258         reg_val = readw(keypad->mmio_base + KPSR);
0259         reg_val |= KBD_STAT_KPKD | KBD_STAT_KDSC;
0260         writew(reg_val, keypad->mmio_base + KPSR);
0261 
0262         reg_val = readw(keypad->mmio_base + KPSR);
0263         reg_val |= KBD_STAT_KDIE;
0264         reg_val &= ~KBD_STAT_KRIE;
0265         writew(reg_val, keypad->mmio_base + KPSR);
0266     } else {
0267         /*
0268          * Some keys are still pressed. Schedule a rescan in
0269          * attempt to detect multiple key presses and enable
0270          * the KRI interrupt to react quickly to key release
0271          * event.
0272          */
0273         mod_timer(&keypad->check_matrix_timer,
0274               jiffies + msecs_to_jiffies(60));
0275 
0276         reg_val = readw(keypad->mmio_base + KPSR);
0277         reg_val |= KBD_STAT_KPKR | KBD_STAT_KRSS;
0278         writew(reg_val, keypad->mmio_base + KPSR);
0279 
0280         reg_val = readw(keypad->mmio_base + KPSR);
0281         reg_val |= KBD_STAT_KRIE;
0282         reg_val &= ~KBD_STAT_KDIE;
0283         writew(reg_val, keypad->mmio_base + KPSR);
0284     }
0285 }
0286 
0287 static irqreturn_t imx_keypad_irq_handler(int irq, void *dev_id)
0288 {
0289     struct imx_keypad *keypad = dev_id;
0290     unsigned short reg_val;
0291 
0292     reg_val = readw(keypad->mmio_base + KPSR);
0293 
0294     /* Disable both interrupt types */
0295     reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
0296     /* Clear interrupts status bits */
0297     reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
0298     writew(reg_val, keypad->mmio_base + KPSR);
0299 
0300     if (keypad->enabled) {
0301         /* The matrix is supposed to be changed */
0302         keypad->stable_count = 0;
0303 
0304         /* Schedule the scanning procedure near in the future */
0305         mod_timer(&keypad->check_matrix_timer,
0306               jiffies + msecs_to_jiffies(2));
0307     }
0308 
0309     return IRQ_HANDLED;
0310 }
0311 
0312 static void imx_keypad_config(struct imx_keypad *keypad)
0313 {
0314     unsigned short reg_val;
0315 
0316     /*
0317      * Include enabled rows in interrupt generation (KPCR[7:0])
0318      * Configure keypad columns as open-drain (KPCR[15:8])
0319      */
0320     reg_val = readw(keypad->mmio_base + KPCR);
0321     reg_val |= keypad->rows_en_mask & 0xff;     /* rows */
0322     reg_val |= (keypad->cols_en_mask & 0xff) << 8;  /* cols */
0323     writew(reg_val, keypad->mmio_base + KPCR);
0324 
0325     /* Write 0's to KPDR[15:8] (Colums) */
0326     reg_val = readw(keypad->mmio_base + KPDR);
0327     reg_val &= 0x00ff;
0328     writew(reg_val, keypad->mmio_base + KPDR);
0329 
0330     /* Configure columns as output, rows as input (KDDR[15:0]) */
0331     writew(0xff00, keypad->mmio_base + KDDR);
0332 
0333     /*
0334      * Clear Key Depress and Key Release status bit.
0335      * Clear both synchronizer chain.
0336      */
0337     reg_val = readw(keypad->mmio_base + KPSR);
0338     reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD |
0339            KBD_STAT_KDSC | KBD_STAT_KRSS;
0340     writew(reg_val, keypad->mmio_base + KPSR);
0341 
0342     /* Enable KDI and disable KRI (avoid false release events). */
0343     reg_val |= KBD_STAT_KDIE;
0344     reg_val &= ~KBD_STAT_KRIE;
0345     writew(reg_val, keypad->mmio_base + KPSR);
0346 }
0347 
0348 static void imx_keypad_inhibit(struct imx_keypad *keypad)
0349 {
0350     unsigned short reg_val;
0351 
0352     /* Inhibit KDI and KRI interrupts. */
0353     reg_val = readw(keypad->mmio_base + KPSR);
0354     reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
0355     reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
0356     writew(reg_val, keypad->mmio_base + KPSR);
0357 
0358     /* Colums as open drain and disable all rows */
0359     reg_val = (keypad->cols_en_mask & 0xff) << 8;
0360     writew(reg_val, keypad->mmio_base + KPCR);
0361 }
0362 
0363 static void imx_keypad_close(struct input_dev *dev)
0364 {
0365     struct imx_keypad *keypad = input_get_drvdata(dev);
0366 
0367     dev_dbg(&dev->dev, ">%s\n", __func__);
0368 
0369     /* Mark keypad as being inactive */
0370     keypad->enabled = false;
0371     synchronize_irq(keypad->irq);
0372     del_timer_sync(&keypad->check_matrix_timer);
0373 
0374     imx_keypad_inhibit(keypad);
0375 
0376     /* Disable clock unit */
0377     clk_disable_unprepare(keypad->clk);
0378 }
0379 
0380 static int imx_keypad_open(struct input_dev *dev)
0381 {
0382     struct imx_keypad *keypad = input_get_drvdata(dev);
0383     int error;
0384 
0385     dev_dbg(&dev->dev, ">%s\n", __func__);
0386 
0387     /* Enable the kpp clock */
0388     error = clk_prepare_enable(keypad->clk);
0389     if (error)
0390         return error;
0391 
0392     /* We became active from now */
0393     keypad->enabled = true;
0394 
0395     imx_keypad_config(keypad);
0396 
0397     /* Sanity control, not all the rows must be actived now. */
0398     if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) {
0399         dev_err(&dev->dev,
0400             "too many keys pressed, control pins initialisation\n");
0401         goto open_err;
0402     }
0403 
0404     return 0;
0405 
0406 open_err:
0407     imx_keypad_close(dev);
0408     return -EIO;
0409 }
0410 
0411 static const struct of_device_id imx_keypad_of_match[] = {
0412     { .compatible = "fsl,imx21-kpp", },
0413     { /* sentinel */ }
0414 };
0415 MODULE_DEVICE_TABLE(of, imx_keypad_of_match);
0416 
0417 static int imx_keypad_probe(struct platform_device *pdev)
0418 {
0419     struct imx_keypad *keypad;
0420     struct input_dev *input_dev;
0421     int irq, error, i, row, col;
0422 
0423     irq = platform_get_irq(pdev, 0);
0424     if (irq < 0)
0425         return irq;
0426 
0427     input_dev = devm_input_allocate_device(&pdev->dev);
0428     if (!input_dev) {
0429         dev_err(&pdev->dev, "failed to allocate the input device\n");
0430         return -ENOMEM;
0431     }
0432 
0433     keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
0434     if (!keypad) {
0435         dev_err(&pdev->dev, "not enough memory for driver data\n");
0436         return -ENOMEM;
0437     }
0438 
0439     keypad->input_dev = input_dev;
0440     keypad->irq = irq;
0441     keypad->stable_count = 0;
0442 
0443     timer_setup(&keypad->check_matrix_timer,
0444             imx_keypad_check_for_events, 0);
0445 
0446     keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0);
0447     if (IS_ERR(keypad->mmio_base))
0448         return PTR_ERR(keypad->mmio_base);
0449 
0450     keypad->clk = devm_clk_get(&pdev->dev, NULL);
0451     if (IS_ERR(keypad->clk)) {
0452         dev_err(&pdev->dev, "failed to get keypad clock\n");
0453         return PTR_ERR(keypad->clk);
0454     }
0455 
0456     /* Init the Input device */
0457     input_dev->name = pdev->name;
0458     input_dev->id.bustype = BUS_HOST;
0459     input_dev->dev.parent = &pdev->dev;
0460     input_dev->open = imx_keypad_open;
0461     input_dev->close = imx_keypad_close;
0462 
0463     error = matrix_keypad_build_keymap(NULL, NULL,
0464                        MAX_MATRIX_KEY_ROWS,
0465                        MAX_MATRIX_KEY_COLS,
0466                        keypad->keycodes, input_dev);
0467     if (error) {
0468         dev_err(&pdev->dev, "failed to build keymap\n");
0469         return error;
0470     }
0471 
0472     /* Search for rows and cols enabled */
0473     for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
0474         for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
0475             i = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
0476             if (keypad->keycodes[i] != KEY_RESERVED) {
0477                 keypad->rows_en_mask |= 1 << row;
0478                 keypad->cols_en_mask |= 1 << col;
0479             }
0480         }
0481     }
0482     dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
0483     dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);
0484 
0485     __set_bit(EV_REP, input_dev->evbit);
0486     input_set_capability(input_dev, EV_MSC, MSC_SCAN);
0487     input_set_drvdata(input_dev, keypad);
0488 
0489     /* Ensure that the keypad will stay dormant until opened */
0490     error = clk_prepare_enable(keypad->clk);
0491     if (error)
0492         return error;
0493     imx_keypad_inhibit(keypad);
0494     clk_disable_unprepare(keypad->clk);
0495 
0496     error = devm_request_irq(&pdev->dev, irq, imx_keypad_irq_handler, 0,
0497                 pdev->name, keypad);
0498     if (error) {
0499         dev_err(&pdev->dev, "failed to request IRQ\n");
0500         return error;
0501     }
0502 
0503     /* Register the input device */
0504     error = input_register_device(input_dev);
0505     if (error) {
0506         dev_err(&pdev->dev, "failed to register input device\n");
0507         return error;
0508     }
0509 
0510     platform_set_drvdata(pdev, keypad);
0511     device_init_wakeup(&pdev->dev, 1);
0512 
0513     return 0;
0514 }
0515 
0516 static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
0517 {
0518     struct platform_device *pdev = to_platform_device(dev);
0519     struct imx_keypad *kbd = platform_get_drvdata(pdev);
0520     struct input_dev *input_dev = kbd->input_dev;
0521     unsigned short reg_val = readw(kbd->mmio_base + KPSR);
0522 
0523     /* imx kbd can wake up system even clock is disabled */
0524     mutex_lock(&input_dev->mutex);
0525 
0526     if (input_device_enabled(input_dev))
0527         clk_disable_unprepare(kbd->clk);
0528 
0529     mutex_unlock(&input_dev->mutex);
0530 
0531     if (device_may_wakeup(&pdev->dev)) {
0532         if (reg_val & KBD_STAT_KPKD)
0533             reg_val |= KBD_STAT_KRIE;
0534         if (reg_val & KBD_STAT_KPKR)
0535             reg_val |= KBD_STAT_KDIE;
0536         writew(reg_val, kbd->mmio_base + KPSR);
0537 
0538         enable_irq_wake(kbd->irq);
0539     }
0540 
0541     return 0;
0542 }
0543 
0544 static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
0545 {
0546     struct platform_device *pdev = to_platform_device(dev);
0547     struct imx_keypad *kbd = platform_get_drvdata(pdev);
0548     struct input_dev *input_dev = kbd->input_dev;
0549     int ret = 0;
0550 
0551     if (device_may_wakeup(&pdev->dev))
0552         disable_irq_wake(kbd->irq);
0553 
0554     mutex_lock(&input_dev->mutex);
0555 
0556     if (input_device_enabled(input_dev)) {
0557         ret = clk_prepare_enable(kbd->clk);
0558         if (ret)
0559             goto err_clk;
0560     }
0561 
0562 err_clk:
0563     mutex_unlock(&input_dev->mutex);
0564 
0565     return ret;
0566 }
0567 
0568 static const struct dev_pm_ops imx_kbd_pm_ops = {
0569     SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_kbd_noirq_suspend, imx_kbd_noirq_resume)
0570 };
0571 
0572 static struct platform_driver imx_keypad_driver = {
0573     .driver     = {
0574         .name   = "imx-keypad",
0575         .pm = &imx_kbd_pm_ops,
0576         .of_match_table = imx_keypad_of_match,
0577     },
0578     .probe      = imx_keypad_probe,
0579 };
0580 module_platform_driver(imx_keypad_driver);
0581 
0582 MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
0583 MODULE_DESCRIPTION("IMX Keypad Port Driver");
0584 MODULE_LICENSE("GPL v2");
0585 MODULE_ALIAS("platform:imx-keypad");