0001
0002
0003
0004
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
0023
0024 #define KPCR 0x00
0025
0026 #define KPSR 0x02
0027 #define KBD_STAT_KPKD (0x1 << 0)
0028 #define KBD_STAT_KPKR (0x1 << 1)
0029 #define KBD_STAT_KDSC (0x1 << 2)
0030 #define KBD_STAT_KRSS (0x1 << 3)
0031 #define KBD_STAT_KDIE (0x1 << 8)
0032 #define KBD_STAT_KRIE (0x1 << 9)
0033 #define KBD_STAT_KPPEN (0x1 << 10)
0034
0035 #define KDDR 0x04
0036 #define KPDR 0x06
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
0055
0056
0057 #define IMX_KEYPAD_SCANS_FOR_STABILITY 3
0058 int stable_count;
0059
0060 bool enabled;
0061
0062
0063 unsigned short rows_en_mask;
0064 unsigned short cols_en_mask;
0065
0066 unsigned short keycodes[MAX_MATRIX_KEY_NUM];
0067
0068
0069
0070
0071
0072
0073 unsigned short matrix_stable_state[MAX_MATRIX_KEY_COLS];
0074 unsigned short matrix_unstable_state[MAX_MATRIX_KEY_COLS];
0075 };
0076
0077
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
0089
0090
0091
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
0109
0110
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
0118
0119
0120 udelay(5);
0121
0122
0123
0124
0125
0126 reg_val = readw(keypad->mmio_base + KPDR);
0127 matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask;
0128 }
0129
0130
0131
0132
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
0141
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;
0155
0156 bits_changed = keypad->matrix_stable_state[col] ^
0157 matrix_volatile_state[col];
0158
0159 if (bits_changed == 0)
0160 continue;
0161
0162 for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
0163 if ((keypad->rows_en_mask & (1 << row)) == 0)
0164 continue;
0165 if ((bits_changed & (1 << row)) == 0)
0166 continue;
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
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
0208
0209
0210
0211
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
0222
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
0232
0233
0234
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
0255
0256
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
0269
0270
0271
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
0295 reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
0296
0297 reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
0298 writew(reg_val, keypad->mmio_base + KPSR);
0299
0300 if (keypad->enabled) {
0301
0302 keypad->stable_count = 0;
0303
0304
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
0318
0319
0320 reg_val = readw(keypad->mmio_base + KPCR);
0321 reg_val |= keypad->rows_en_mask & 0xff;
0322 reg_val |= (keypad->cols_en_mask & 0xff) << 8;
0323 writew(reg_val, keypad->mmio_base + KPCR);
0324
0325
0326 reg_val = readw(keypad->mmio_base + KPDR);
0327 reg_val &= 0x00ff;
0328 writew(reg_val, keypad->mmio_base + KPDR);
0329
0330
0331 writew(0xff00, keypad->mmio_base + KDDR);
0332
0333
0334
0335
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
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
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
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
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
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
0388 error = clk_prepare_enable(keypad->clk);
0389 if (error)
0390 return error;
0391
0392
0393 keypad->enabled = true;
0394
0395 imx_keypad_config(keypad);
0396
0397
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 { }
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
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
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
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
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
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");