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 48*3fb84000SJoseph Chen int key_parse_adc_event(struct input_key *key, unsigned int adcval) 49*3fb84000SJoseph Chen { 50*3fb84000SJoseph Chen int report = KEY_NOT_EXIST; 51*3fb84000SJoseph Chen int max, min; 52*3fb84000SJoseph Chen 53*3fb84000SJoseph Chen debug("%s: %s: max=%d, min=%d, adcval=%d\n", 54*3fb84000SJoseph Chen __func__, key->name, max, min, adcval); 55*3fb84000SJoseph Chen 56*3fb84000SJoseph Chen /* Get min, max */ 57*3fb84000SJoseph Chen max = key->value + key->margin; 58*3fb84000SJoseph Chen if (key->value > key->margin) 59*3fb84000SJoseph Chen min = key->value - key->margin; 60*3fb84000SJoseph Chen else 61*3fb84000SJoseph Chen min = key->value; 62*3fb84000SJoseph Chen 63*3fb84000SJoseph Chen /* Check */ 64*3fb84000SJoseph Chen if ((adcval <= max) && (adcval >= min)) { 65*3fb84000SJoseph Chen report = KEY_PRESS_DOWN; 66*3fb84000SJoseph Chen printf("%s key pressed..\n", key->name); 67*3fb84000SJoseph Chen } else { 68*3fb84000SJoseph Chen report = KEY_PRESS_NONE; 69*3fb84000SJoseph Chen } 70*3fb84000SJoseph Chen 71*3fb84000SJoseph Chen return report; 72*3fb84000SJoseph Chen } 73*3fb84000SJoseph Chen 74*3fb84000SJoseph Chen int key_parse_gpio_event(struct input_key *key) 75*3fb84000SJoseph Chen { 76*3fb84000SJoseph Chen u32 report = KEY_NOT_EXIST; 77*3fb84000SJoseph Chen 78*3fb84000SJoseph Chen debug("%s: %s: up=%llu, down=%llu, delta=%llu\n", 79*3fb84000SJoseph Chen __func__, key->name, key->up_t, key->down_t, 80*3fb84000SJoseph Chen key->up_t - key->down_t); 81*3fb84000SJoseph Chen 82*3fb84000SJoseph Chen /* Possible this is machine power-on long pressed, so ignore this */ 83*3fb84000SJoseph Chen if (key->down_t == 0 && key->up_t != 0) { 84*3fb84000SJoseph Chen report = KEY_PRESS_NONE; 85*3fb84000SJoseph Chen goto out; 86*3fb84000SJoseph Chen } 87*3fb84000SJoseph Chen 88*3fb84000SJoseph Chen if ((key->up_t > key->down_t) && 89*3fb84000SJoseph Chen (key->up_t - key->down_t) >= KEY_LONG_DOWN_MS) { 90*3fb84000SJoseph Chen key->up_t = 0; 91*3fb84000SJoseph Chen key->down_t = 0; 92*3fb84000SJoseph Chen report = KEY_PRESS_LONG_DOWN; 93*3fb84000SJoseph Chen printf("%s key long pressed(hold)..\n", key->name); 94*3fb84000SJoseph Chen } else if (key->down_t && 95*3fb84000SJoseph Chen key_get_timer(key->down_t) >= KEY_LONG_DOWN_MS) { 96*3fb84000SJoseph Chen key->up_t = 0; 97*3fb84000SJoseph Chen key->down_t = 0; 98*3fb84000SJoseph Chen report = KEY_PRESS_LONG_DOWN; 99*3fb84000SJoseph Chen printf("%s key long pressed..\n", key->name); 100*3fb84000SJoseph Chen } else if ((key->up_t > key->down_t) && 101*3fb84000SJoseph Chen (key->up_t - key->down_t) < KEY_LONG_DOWN_MS) { 102*3fb84000SJoseph Chen key->up_t = 0; 103*3fb84000SJoseph Chen key->down_t = 0; 104*3fb84000SJoseph Chen report = KEY_PRESS_DOWN; 105*3fb84000SJoseph Chen printf("%s key short pressed..\n", key->name); 106*3fb84000SJoseph Chen } else { 107*3fb84000SJoseph Chen report = KEY_PRESS_NONE; 108*3fb84000SJoseph Chen } 109*3fb84000SJoseph Chen 110*3fb84000SJoseph Chen out: 111*3fb84000SJoseph Chen return report; 112*3fb84000SJoseph Chen } 113*3fb84000SJoseph 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