1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <dm.h> 8 #include <key.h> 9 #include <common.h> 10 #include <dm.h> 11 12 static inline uint64_t arch_counter_get_cntpct(void) 13 { 14 uint64_t cval = 0; 15 16 isb(); 17 #ifdef CONFIG_ARM64 18 asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); 19 #else 20 asm volatile ("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); 21 #endif 22 return cval; 23 } 24 25 uint64_t key_get_timer(uint64_t base) 26 { 27 uint64_t cntpct; 28 29 cntpct = arch_counter_get_cntpct() / 24000UL; 30 return (cntpct > base) ? (cntpct - base) : 0; 31 } 32 33 static int key_state_valid(int state) 34 { 35 return (state >= KEY_PRESS_NONE && state < KEY_NOT_EXIST); 36 } 37 38 static int key_read(struct udevice *dev, int code) 39 { 40 const struct dm_key_ops *ops = dev_get_driver_ops(dev); 41 42 if (!ops || !ops->read) 43 return -ENOSYS; 44 45 return ops->read(dev, code); 46 } 47 48 int key_parse_adc_event(struct input_key *key, unsigned int adcval) 49 { 50 int report = KEY_NOT_EXIST; 51 int max, min; 52 53 /* Get min, max */ 54 max = key->value + key->margin; 55 if (key->value > key->margin) 56 min = key->value - key->margin; 57 else 58 min = key->value; 59 60 debug("%s: %s: max=%d, min=%d, adcval=%d\n", 61 __func__, key->name, max, min, adcval); 62 63 /* Check */ 64 if ((adcval <= max) && (adcval >= min)) { 65 report = KEY_PRESS_DOWN; 66 printf("%s key pressed..\n", key->name); 67 } else { 68 report = KEY_PRESS_NONE; 69 } 70 71 return report; 72 } 73 74 int key_parse_gpio_event(struct input_key *key) 75 { 76 u32 report = KEY_NOT_EXIST; 77 78 debug("%s: %s: up=%llu, down=%llu, delta=%llu\n", 79 __func__, key->name, key->up_t, key->down_t, 80 key->up_t - key->down_t); 81 82 /* Possible this is machine power-on long pressed, so ignore this */ 83 if (key->down_t == 0 && key->up_t != 0) { 84 report = KEY_PRESS_NONE; 85 goto out; 86 } 87 88 if ((key->up_t > key->down_t) && 89 (key->up_t - key->down_t) >= KEY_LONG_DOWN_MS) { 90 key->up_t = 0; 91 key->down_t = 0; 92 report = KEY_PRESS_LONG_DOWN; 93 printf("%s key long pressed(hold)..\n", key->name); 94 } else if (key->down_t && 95 key_get_timer(key->down_t) >= KEY_LONG_DOWN_MS) { 96 key->up_t = 0; 97 key->down_t = 0; 98 report = KEY_PRESS_LONG_DOWN; 99 printf("%s key long pressed..\n", key->name); 100 } else if ((key->up_t > key->down_t) && 101 (key->up_t - key->down_t) < KEY_LONG_DOWN_MS) { 102 key->up_t = 0; 103 key->down_t = 0; 104 report = KEY_PRESS_DOWN; 105 printf("%s key short pressed..\n", key->name); 106 } else { 107 report = KEY_PRESS_NONE; 108 } 109 110 out: 111 return report; 112 } 113 114 int platform_key_read(int code) 115 { 116 struct udevice *dev; 117 int report = KEY_NOT_EXIST; 118 119 for (uclass_first_device(UCLASS_KEY, &dev); 120 dev; 121 uclass_next_device(&dev)) { 122 debug("key dev.name = %s, code = %d\n", dev->name, code); 123 report = key_read(dev, code); 124 if (key_state_valid(report)) { 125 debug("key dev.name = %s, state=%d\n", dev->name, report); 126 break; 127 } 128 } 129 130 return report; 131 } 132 133 UCLASS_DRIVER(key) = { 134 .id = UCLASS_KEY, 135 .name = "key", 136 }; 137