xref: /rk3399_rockchip-uboot/drivers/input/key-uclass.c (revision d5f538dc02e53c7267fcd4a914104071fca889b5)
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