1b398a9a7SJoseph Chen /* 2b398a9a7SJoseph Chen * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3b398a9a7SJoseph Chen * 4b398a9a7SJoseph Chen * SPDX-License-Identifier: GPL-2.0+ 5b398a9a7SJoseph Chen */ 6b398a9a7SJoseph Chen 7b398a9a7SJoseph Chen #include <dm.h> 8b398a9a7SJoseph Chen #include <key.h> 9a2df9606SJoseph Chen #include <common.h> 10a2df9606SJoseph Chen #include <dm.h> 11b398a9a7SJoseph Chen 12a2df9606SJoseph Chen static inline uint64_t arch_counter_get_cntpct(void) 13a2df9606SJoseph Chen { 14a2df9606SJoseph Chen uint64_t cval = 0; 15a2df9606SJoseph Chen 16a2df9606SJoseph Chen isb(); 17a2df9606SJoseph Chen #ifdef CONFIG_ARM64 18a2df9606SJoseph Chen asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); 19a2df9606SJoseph Chen #else 20a2df9606SJoseph Chen asm volatile ("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); 21a2df9606SJoseph Chen #endif 22a2df9606SJoseph Chen return cval; 23a2df9606SJoseph Chen } 24a2df9606SJoseph Chen 25a2df9606SJoseph Chen uint64_t key_get_timer(uint64_t base) 26a2df9606SJoseph Chen { 27a2df9606SJoseph Chen uint64_t cntpct; 28a2df9606SJoseph Chen 29a2df9606SJoseph Chen cntpct = arch_counter_get_cntpct() / 24000UL; 30a2df9606SJoseph Chen return (cntpct > base) ? (cntpct - base) : 0; 31a2df9606SJoseph Chen } 32a2df9606SJoseph Chen 33a2df9606SJoseph Chen static int key_state_valid(int state) 34a2df9606SJoseph Chen { 35a2df9606SJoseph Chen return (state >= KEY_PRESS_NONE && state < KEY_NOT_EXIST); 36a2df9606SJoseph Chen } 37a2df9606SJoseph Chen 38a2df9606SJoseph Chen static int key_read(struct udevice *dev, int code) 39b398a9a7SJoseph Chen { 40b398a9a7SJoseph Chen const struct dm_key_ops *ops = dev_get_driver_ops(dev); 41b398a9a7SJoseph Chen 42b398a9a7SJoseph Chen if (!ops || !ops->read) 43b398a9a7SJoseph Chen return -ENOSYS; 44b398a9a7SJoseph Chen 45a2df9606SJoseph Chen return ops->read(dev, code); 46b398a9a7SJoseph Chen } 47b398a9a7SJoseph Chen 483fb84000SJoseph Chen int key_parse_adc_event(struct input_key *key, unsigned int adcval) 493fb84000SJoseph Chen { 503fb84000SJoseph Chen int report = KEY_NOT_EXIST; 513fb84000SJoseph Chen int max, min; 523fb84000SJoseph Chen 533fb84000SJoseph Chen /* Get min, max */ 543fb84000SJoseph Chen max = key->value + key->margin; 553fb84000SJoseph Chen if (key->value > key->margin) 563fb84000SJoseph Chen min = key->value - key->margin; 573fb84000SJoseph Chen else 583fb84000SJoseph Chen min = key->value; 593fb84000SJoseph Chen 60*33385721SJoseph Chen debug("%s: %s: max=%d, min=%d, adcval=%d\n", 61*33385721SJoseph Chen __func__, key->name, max, min, adcval); 62*33385721SJoseph Chen 633fb84000SJoseph Chen /* Check */ 643fb84000SJoseph Chen if ((adcval <= max) && (adcval >= min)) { 653fb84000SJoseph Chen report = KEY_PRESS_DOWN; 663fb84000SJoseph Chen printf("%s key pressed..\n", key->name); 673fb84000SJoseph Chen } else { 683fb84000SJoseph Chen report = KEY_PRESS_NONE; 693fb84000SJoseph Chen } 703fb84000SJoseph Chen 713fb84000SJoseph Chen return report; 723fb84000SJoseph Chen } 733fb84000SJoseph Chen 743fb84000SJoseph Chen int key_parse_gpio_event(struct input_key *key) 753fb84000SJoseph Chen { 763fb84000SJoseph Chen u32 report = KEY_NOT_EXIST; 773fb84000SJoseph Chen 783fb84000SJoseph Chen debug("%s: %s: up=%llu, down=%llu, delta=%llu\n", 793fb84000SJoseph Chen __func__, key->name, key->up_t, key->down_t, 803fb84000SJoseph Chen key->up_t - key->down_t); 813fb84000SJoseph Chen 823fb84000SJoseph Chen /* Possible this is machine power-on long pressed, so ignore this */ 833fb84000SJoseph Chen if (key->down_t == 0 && key->up_t != 0) { 843fb84000SJoseph Chen report = KEY_PRESS_NONE; 853fb84000SJoseph Chen goto out; 863fb84000SJoseph Chen } 873fb84000SJoseph Chen 883fb84000SJoseph Chen if ((key->up_t > key->down_t) && 893fb84000SJoseph Chen (key->up_t - key->down_t) >= KEY_LONG_DOWN_MS) { 903fb84000SJoseph Chen key->up_t = 0; 913fb84000SJoseph Chen key->down_t = 0; 923fb84000SJoseph Chen report = KEY_PRESS_LONG_DOWN; 933fb84000SJoseph Chen printf("%s key long pressed(hold)..\n", key->name); 943fb84000SJoseph Chen } else if (key->down_t && 953fb84000SJoseph Chen key_get_timer(key->down_t) >= KEY_LONG_DOWN_MS) { 963fb84000SJoseph Chen key->up_t = 0; 973fb84000SJoseph Chen key->down_t = 0; 983fb84000SJoseph Chen report = KEY_PRESS_LONG_DOWN; 993fb84000SJoseph Chen printf("%s key long pressed..\n", key->name); 1003fb84000SJoseph Chen } else if ((key->up_t > key->down_t) && 1013fb84000SJoseph Chen (key->up_t - key->down_t) < KEY_LONG_DOWN_MS) { 1023fb84000SJoseph Chen key->up_t = 0; 1033fb84000SJoseph Chen key->down_t = 0; 1043fb84000SJoseph Chen report = KEY_PRESS_DOWN; 1053fb84000SJoseph Chen printf("%s key short pressed..\n", key->name); 1063fb84000SJoseph Chen } else { 1073fb84000SJoseph Chen report = KEY_PRESS_NONE; 1083fb84000SJoseph Chen } 1093fb84000SJoseph Chen 1103fb84000SJoseph Chen out: 1113fb84000SJoseph Chen return report; 1123fb84000SJoseph Chen } 1133fb84000SJoseph Chen 114a2df9606SJoseph Chen int platform_key_read(int code) 1156e14addfSJoseph Chen { 116a2df9606SJoseph Chen struct udevice *dev; 117a2df9606SJoseph Chen int report = KEY_NOT_EXIST; 1186e14addfSJoseph Chen 119a2df9606SJoseph Chen for (uclass_first_device(UCLASS_KEY, &dev); 120a2df9606SJoseph Chen dev; 121a2df9606SJoseph Chen uclass_next_device(&dev)) { 122a2df9606SJoseph Chen debug("key dev.name = %s, code = %d\n", dev->name, code); 123a2df9606SJoseph Chen report = key_read(dev, code); 124a2df9606SJoseph Chen if (key_state_valid(report)) { 125a2df9606SJoseph Chen debug("key dev.name = %s, state=%d\n", dev->name, report); 126a2df9606SJoseph Chen break; 127a2df9606SJoseph Chen } 1286e14addfSJoseph Chen } 1296e14addfSJoseph Chen 130a2df9606SJoseph Chen return report; 1316e14addfSJoseph Chen } 1326e14addfSJoseph Chen 133b398a9a7SJoseph Chen UCLASS_DRIVER(key) = { 134b398a9a7SJoseph Chen .id = UCLASS_KEY, 135b398a9a7SJoseph Chen .name = "key", 136b398a9a7SJoseph Chen }; 137