Lines Matching +full:key +full:- +full:release
1 // SPDX-License-Identifier: GPL-2.0
28 #define KBD_STAT_KPKD (0x1 << 0) /* Key Press Interrupt Status bit (w1c) */
29 #define KBD_STAT_KPKR (0x1 << 1) /* Key Release Interrupt Status bit (w1c) */
30 #define KBD_STAT_KDSC (0x1 << 2) /* Key Depress Synch Chain Status bit (w1c)*/
31 #define KBD_STAT_KRSS (0x1 << 3) /* Key Release Synch Status bit (w1c)*/
32 #define KBD_STAT_KDIE (0x1 << 8) /* Key Depress Interrupt Enable Status bit */
33 #define KBD_STAT_KRIE (0x1 << 9) /* Key Release Interrupt Enable */
71 * -stable: achieved after a complete debounce process.
72 * -unstable: used in the debouncing process.
86 if ((keypad->cols_en_mask & (1 << col)) == 0) in imx_keypad_scan_matrix()
91 * 3. configure columns as totem-pole to discharge capacitance. in imx_keypad_scan_matrix()
92 * 4. configure columns as open-drain. in imx_keypad_scan_matrix()
94 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
96 writew(reg_val, keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
98 reg_val = readw(keypad->mmio_base + KPCR); in imx_keypad_scan_matrix()
99 reg_val &= ~((keypad->cols_en_mask & 0xff) << 8); in imx_keypad_scan_matrix()
100 writew(reg_val, keypad->mmio_base + KPCR); in imx_keypad_scan_matrix()
104 reg_val = readw(keypad->mmio_base + KPCR); in imx_keypad_scan_matrix()
105 reg_val |= (keypad->cols_en_mask & 0xff) << 8; in imx_keypad_scan_matrix()
106 writew(reg_val, keypad->mmio_base + KPCR); in imx_keypad_scan_matrix()
111 * 7. Repeat steps 2 - 6 for remaining columns. in imx_keypad_scan_matrix()
113 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
115 writew(reg_val, keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
124 * 1s in matrix_volatile_state[col] means key pressures in imx_keypad_scan_matrix()
127 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
128 matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask; in imx_keypad_scan_matrix()
135 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
137 writew(reg_val, keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
142 * keypad->matrix_stable_state and fire events if changes are detected.
147 struct input_dev *input_dev = keypad->input_dev; in imx_keypad_fire_events()
154 if ((keypad->cols_en_mask & (1 << col)) == 0) in imx_keypad_fire_events()
157 bits_changed = keypad->matrix_stable_state[col] ^ in imx_keypad_fire_events()
164 if ((keypad->rows_en_mask & (1 << row)) == 0) in imx_keypad_fire_events()
171 input_report_key(input_dev, keypad->keycodes[code], in imx_keypad_fire_events()
173 dev_dbg(&input_dev->dev, "Event code: %d, val: %d", in imx_keypad_fire_events()
174 keypad->keycodes[code], in imx_keypad_fire_events()
198 if ((keypad->cols_en_mask & (1 << i)) == 0) in imx_keypad_check_for_events()
201 if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) { in imx_keypad_check_for_events()
210 * keypad->matrix_unstable_state. in imx_keypad_check_for_events()
215 memcpy(keypad->matrix_unstable_state, matrix_volatile_state, in imx_keypad_check_for_events()
217 keypad->stable_count = 0; in imx_keypad_check_for_events()
219 keypad->stable_count++; in imx_keypad_check_for_events()
225 if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) { in imx_keypad_check_for_events()
226 mod_timer(&keypad->check_matrix_timer, in imx_keypad_check_for_events()
234 * (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all in imx_keypad_check_for_events()
237 if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) { in imx_keypad_check_for_events()
240 memcpy(keypad->matrix_stable_state, matrix_volatile_state, in imx_keypad_check_for_events()
256 * interrupt for future key presses (clear the KDI in imx_keypad_check_for_events()
259 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
261 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
263 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
266 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
270 * attempt to detect multiple key presses and enable in imx_keypad_check_for_events()
271 * the KRI interrupt to react quickly to key release in imx_keypad_check_for_events()
274 mod_timer(&keypad->check_matrix_timer, in imx_keypad_check_for_events()
277 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
279 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
281 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
284 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
293 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_irq_handler()
299 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_irq_handler()
301 if (keypad->enabled) { in imx_keypad_irq_handler()
303 keypad->stable_count = 0; in imx_keypad_irq_handler()
306 mod_timer(&keypad->check_matrix_timer, in imx_keypad_irq_handler()
319 * Configure keypad columns as open-drain (KPCR[15:8]) in imx_keypad_config()
321 reg_val = readw(keypad->mmio_base + KPCR); in imx_keypad_config()
322 reg_val |= keypad->rows_en_mask & 0xff; /* rows */ in imx_keypad_config()
323 reg_val |= (keypad->cols_en_mask & 0xff) << 8; /* cols */ in imx_keypad_config()
324 writew(reg_val, keypad->mmio_base + KPCR); in imx_keypad_config()
327 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_config()
329 writew(reg_val, keypad->mmio_base + KPDR); in imx_keypad_config()
332 writew(0xff00, keypad->mmio_base + KDDR); in imx_keypad_config()
335 * Clear Key Depress and Key Release status bit. in imx_keypad_config()
338 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_config()
341 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_config()
343 /* Enable KDI and disable KRI (avoid false release events). */ in imx_keypad_config()
346 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_config()
354 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_inhibit()
357 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_inhibit()
360 reg_val = (keypad->cols_en_mask & 0xff) << 8; in imx_keypad_inhibit()
361 writew(reg_val, keypad->mmio_base + KPCR); in imx_keypad_inhibit()
368 dev_dbg(&dev->dev, ">%s\n", __func__); in imx_keypad_close()
371 keypad->enabled = false; in imx_keypad_close()
372 synchronize_irq(keypad->irq); in imx_keypad_close()
373 del_timer_sync(&keypad->check_matrix_timer); in imx_keypad_close()
378 clk_disable_unprepare(keypad->clk); in imx_keypad_close()
386 dev_dbg(&dev->dev, ">%s\n", __func__); in imx_keypad_open()
389 error = clk_prepare_enable(keypad->clk); in imx_keypad_open()
394 keypad->enabled = true; in imx_keypad_open()
399 if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) { in imx_keypad_open()
400 dev_err(&dev->dev, in imx_keypad_open()
409 return -EIO; in imx_keypad_open()
413 { .compatible = "fsl,imx21-kpp", },
428 input_dev = devm_input_allocate_device(&pdev->dev); in imx_keypad_probe()
430 dev_err(&pdev->dev, "failed to allocate the input device\n"); in imx_keypad_probe()
431 return -ENOMEM; in imx_keypad_probe()
434 keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL); in imx_keypad_probe()
436 dev_err(&pdev->dev, "not enough memory for driver data\n"); in imx_keypad_probe()
437 return -ENOMEM; in imx_keypad_probe()
440 keypad->input_dev = input_dev; in imx_keypad_probe()
441 keypad->irq = irq; in imx_keypad_probe()
442 keypad->stable_count = 0; in imx_keypad_probe()
444 timer_setup(&keypad->check_matrix_timer, in imx_keypad_probe()
447 keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0); in imx_keypad_probe()
448 if (IS_ERR(keypad->mmio_base)) in imx_keypad_probe()
449 return PTR_ERR(keypad->mmio_base); in imx_keypad_probe()
451 keypad->clk = devm_clk_get(&pdev->dev, NULL); in imx_keypad_probe()
452 if (IS_ERR(keypad->clk)) { in imx_keypad_probe()
453 dev_err(&pdev->dev, "failed to get keypad clock\n"); in imx_keypad_probe()
454 return PTR_ERR(keypad->clk); in imx_keypad_probe()
458 input_dev->name = pdev->name; in imx_keypad_probe()
459 input_dev->id.bustype = BUS_HOST; in imx_keypad_probe()
460 input_dev->dev.parent = &pdev->dev; in imx_keypad_probe()
461 input_dev->open = imx_keypad_open; in imx_keypad_probe()
462 input_dev->close = imx_keypad_close; in imx_keypad_probe()
467 keypad->keycodes, input_dev); in imx_keypad_probe()
469 dev_err(&pdev->dev, "failed to build keymap\n"); in imx_keypad_probe()
477 if (keypad->keycodes[i] != KEY_RESERVED) { in imx_keypad_probe()
478 keypad->rows_en_mask |= 1 << row; in imx_keypad_probe()
479 keypad->cols_en_mask |= 1 << col; in imx_keypad_probe()
483 dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask); in imx_keypad_probe()
484 dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask); in imx_keypad_probe()
486 __set_bit(EV_REP, input_dev->evbit); in imx_keypad_probe()
491 error = clk_prepare_enable(keypad->clk); in imx_keypad_probe()
495 clk_disable_unprepare(keypad->clk); in imx_keypad_probe()
497 error = devm_request_irq(&pdev->dev, irq, imx_keypad_irq_handler, 0, in imx_keypad_probe()
498 pdev->name, keypad); in imx_keypad_probe()
500 dev_err(&pdev->dev, "failed to request IRQ\n"); in imx_keypad_probe()
507 dev_err(&pdev->dev, "failed to register input device\n"); in imx_keypad_probe()
512 device_init_wakeup(&pdev->dev, 1); in imx_keypad_probe()
521 struct input_dev *input_dev = kbd->input_dev; in imx_kbd_noirq_suspend()
522 unsigned short reg_val = readw(kbd->mmio_base + KPSR); in imx_kbd_noirq_suspend()
524 scoped_guard(mutex, &input_dev->mutex) { in imx_kbd_noirq_suspend()
527 clk_disable_unprepare(kbd->clk); in imx_kbd_noirq_suspend()
530 if (device_may_wakeup(&pdev->dev)) { in imx_kbd_noirq_suspend()
535 writew(reg_val, kbd->mmio_base + KPSR); in imx_kbd_noirq_suspend()
537 enable_irq_wake(kbd->irq); in imx_kbd_noirq_suspend()
547 struct input_dev *input_dev = kbd->input_dev; in imx_kbd_noirq_resume()
550 if (device_may_wakeup(&pdev->dev)) in imx_kbd_noirq_resume()
551 disable_irq_wake(kbd->irq); in imx_kbd_noirq_resume()
553 guard(mutex)(&input_dev->mutex); in imx_kbd_noirq_resume()
556 error = clk_prepare_enable(kbd->clk); in imx_kbd_noirq_resume()
570 .name = "imx-keypad",
581 MODULE_ALIAS("platform:imx-keypad");