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