Lines Matching full:keypad

3 // Driver for the IMX keypad port.
22 * Keypad Controller registers (halfword)
24 #define KPCR 0x00 /* Keypad Control Register */
26 #define KPSR 0x02 /* Keypad Status Register */
33 #define KBD_STAT_KPPEN (0x1 << 10) /* Keypad Clock Enable */
35 #define KDDR 0x04 /* Keypad Data Direction Register */
36 #define KPDR 0x06 /* Keypad Data Register */
78 static void imx_keypad_scan_matrix(struct imx_keypad *keypad, in imx_keypad_scan_matrix() argument
85 if ((keypad->cols_en_mask & (1 << col)) == 0) in imx_keypad_scan_matrix()
88 * Discharge keypad capacitance: in imx_keypad_scan_matrix()
93 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
95 writew(reg_val, keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
97 reg_val = readw(keypad->mmio_base + KPCR); in imx_keypad_scan_matrix()
98 reg_val &= ~((keypad->cols_en_mask & 0xff) << 8); in imx_keypad_scan_matrix()
99 writew(reg_val, keypad->mmio_base + KPCR); in imx_keypad_scan_matrix()
103 reg_val = readw(keypad->mmio_base + KPCR); in imx_keypad_scan_matrix()
104 reg_val |= (keypad->cols_en_mask & 0xff) << 8; in imx_keypad_scan_matrix()
105 writew(reg_val, keypad->mmio_base + KPCR); in imx_keypad_scan_matrix()
112 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
114 writew(reg_val, keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
126 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
127 matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask; in imx_keypad_scan_matrix()
134 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
136 writew(reg_val, keypad->mmio_base + KPDR); in imx_keypad_scan_matrix()
141 * keypad->matrix_stable_state and fire events if changes are detected.
143 static void imx_keypad_fire_events(struct imx_keypad *keypad, in imx_keypad_fire_events() argument
146 struct input_dev *input_dev = keypad->input_dev; in imx_keypad_fire_events()
153 if ((keypad->cols_en_mask & (1 << col)) == 0) in imx_keypad_fire_events()
156 bits_changed = keypad->matrix_stable_state[col] ^ in imx_keypad_fire_events()
163 if ((keypad->rows_en_mask & (1 << row)) == 0) in imx_keypad_fire_events()
170 input_report_key(input_dev, keypad->keycodes[code], in imx_keypad_fire_events()
173 keypad->keycodes[code], in imx_keypad_fire_events()
185 struct imx_keypad *keypad = from_timer(keypad, t, check_matrix_timer); in imx_keypad_check_for_events() local
193 imx_keypad_scan_matrix(keypad, matrix_volatile_state); in imx_keypad_check_for_events()
197 if ((keypad->cols_en_mask & (1 << i)) == 0) in imx_keypad_check_for_events()
200 if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) { in imx_keypad_check_for_events()
209 * keypad->matrix_unstable_state. in imx_keypad_check_for_events()
214 memcpy(keypad->matrix_unstable_state, matrix_volatile_state, in imx_keypad_check_for_events()
216 keypad->stable_count = 0; in imx_keypad_check_for_events()
218 keypad->stable_count++; in imx_keypad_check_for_events()
224 if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) { in imx_keypad_check_for_events()
225 mod_timer(&keypad->check_matrix_timer, in imx_keypad_check_for_events()
233 * (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all in imx_keypad_check_for_events()
236 if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) { in imx_keypad_check_for_events()
237 imx_keypad_fire_events(keypad, matrix_volatile_state); in imx_keypad_check_for_events()
239 memcpy(keypad->matrix_stable_state, matrix_volatile_state, in imx_keypad_check_for_events()
258 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
260 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
262 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
265 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
273 mod_timer(&keypad->check_matrix_timer, in imx_keypad_check_for_events()
276 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
278 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
280 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
283 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_check_for_events()
289 struct imx_keypad *keypad = dev_id; in imx_keypad_irq_handler() local
292 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_irq_handler()
298 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_irq_handler()
300 if (keypad->enabled) { in imx_keypad_irq_handler()
302 keypad->stable_count = 0; in imx_keypad_irq_handler()
305 mod_timer(&keypad->check_matrix_timer, in imx_keypad_irq_handler()
312 static void imx_keypad_config(struct imx_keypad *keypad) in imx_keypad_config() argument
318 * Configure keypad columns as open-drain (KPCR[15:8]) in imx_keypad_config()
320 reg_val = readw(keypad->mmio_base + KPCR); in imx_keypad_config()
321 reg_val |= keypad->rows_en_mask & 0xff; /* rows */ in imx_keypad_config()
322 reg_val |= (keypad->cols_en_mask & 0xff) << 8; /* cols */ in imx_keypad_config()
323 writew(reg_val, keypad->mmio_base + KPCR); in imx_keypad_config()
326 reg_val = readw(keypad->mmio_base + KPDR); in imx_keypad_config()
328 writew(reg_val, keypad->mmio_base + KPDR); in imx_keypad_config()
331 writew(0xff00, keypad->mmio_base + KDDR); in imx_keypad_config()
337 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_config()
340 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_config()
345 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_config()
348 static void imx_keypad_inhibit(struct imx_keypad *keypad) in imx_keypad_inhibit() argument
353 reg_val = readw(keypad->mmio_base + KPSR); in imx_keypad_inhibit()
356 writew(reg_val, keypad->mmio_base + KPSR); in imx_keypad_inhibit()
359 reg_val = (keypad->cols_en_mask & 0xff) << 8; in imx_keypad_inhibit()
360 writew(reg_val, keypad->mmio_base + KPCR); in imx_keypad_inhibit()
365 struct imx_keypad *keypad = input_get_drvdata(dev); in imx_keypad_close() local
369 /* Mark keypad as being inactive */ in imx_keypad_close()
370 keypad->enabled = false; in imx_keypad_close()
371 synchronize_irq(keypad->irq); in imx_keypad_close()
372 del_timer_sync(&keypad->check_matrix_timer); in imx_keypad_close()
374 imx_keypad_inhibit(keypad); in imx_keypad_close()
377 clk_disable_unprepare(keypad->clk); in imx_keypad_close()
382 struct imx_keypad *keypad = input_get_drvdata(dev); in imx_keypad_open() local
388 error = clk_prepare_enable(keypad->clk); in imx_keypad_open()
393 keypad->enabled = true; in imx_keypad_open()
395 imx_keypad_config(keypad); in imx_keypad_open()
398 if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) { in imx_keypad_open()
423 struct imx_keypad *keypad; in imx_keypad_probe() local
442 keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL); in imx_keypad_probe()
443 if (!keypad) { in imx_keypad_probe()
448 keypad->input_dev = input_dev; in imx_keypad_probe()
449 keypad->irq = irq; in imx_keypad_probe()
450 keypad->stable_count = 0; in imx_keypad_probe()
452 timer_setup(&keypad->check_matrix_timer, in imx_keypad_probe()
455 keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0); in imx_keypad_probe()
456 if (IS_ERR(keypad->mmio_base)) in imx_keypad_probe()
457 return PTR_ERR(keypad->mmio_base); in imx_keypad_probe()
459 keypad->clk = devm_clk_get(&pdev->dev, NULL); in imx_keypad_probe()
460 if (IS_ERR(keypad->clk)) { in imx_keypad_probe()
461 dev_err(&pdev->dev, "failed to get keypad clock\n"); in imx_keypad_probe()
462 return PTR_ERR(keypad->clk); in imx_keypad_probe()
475 keypad->keycodes, input_dev); in imx_keypad_probe()
485 if (keypad->keycodes[i] != KEY_RESERVED) { in imx_keypad_probe()
486 keypad->rows_en_mask |= 1 << row; in imx_keypad_probe()
487 keypad->cols_en_mask |= 1 << col; in imx_keypad_probe()
491 dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask); in imx_keypad_probe()
492 dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask); in imx_keypad_probe()
496 input_set_drvdata(input_dev, keypad); in imx_keypad_probe()
498 /* Ensure that the keypad will stay dormant until opened */ in imx_keypad_probe()
499 error = clk_prepare_enable(keypad->clk); in imx_keypad_probe()
502 imx_keypad_inhibit(keypad); in imx_keypad_probe()
503 clk_disable_unprepare(keypad->clk); in imx_keypad_probe()
506 pdev->name, keypad); in imx_keypad_probe()
519 platform_set_drvdata(pdev, keypad); in imx_keypad_probe()
583 .name = "imx-keypad",
592 MODULE_DESCRIPTION("IMX Keypad Port Driver");
594 MODULE_ALIAS("platform:imx-keypad");