xref: /rk3399_rockchip-uboot/drivers/input/key-uclass.c (revision a2df960601036d3fd0d00ea8f43cdde52b5eddbe)
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>
9*a2df9606SJoseph Chen #include <common.h>
10*a2df9606SJoseph Chen #include <dm.h>
11b398a9a7SJoseph Chen 
12*a2df9606SJoseph Chen static inline uint64_t arch_counter_get_cntpct(void)
13*a2df9606SJoseph Chen {
14*a2df9606SJoseph Chen 	uint64_t cval = 0;
15*a2df9606SJoseph Chen 
16*a2df9606SJoseph Chen 	isb();
17*a2df9606SJoseph Chen #ifdef CONFIG_ARM64
18*a2df9606SJoseph Chen 	asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
19*a2df9606SJoseph Chen #else
20*a2df9606SJoseph Chen 	asm volatile ("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
21*a2df9606SJoseph Chen #endif
22*a2df9606SJoseph Chen 	return cval;
23*a2df9606SJoseph Chen }
24*a2df9606SJoseph Chen 
25*a2df9606SJoseph Chen uint64_t key_get_timer(uint64_t base)
26*a2df9606SJoseph Chen {
27*a2df9606SJoseph Chen 	uint64_t cntpct;
28*a2df9606SJoseph Chen 
29*a2df9606SJoseph Chen 	cntpct = arch_counter_get_cntpct() / 24000UL;
30*a2df9606SJoseph Chen 	return (cntpct > base) ? (cntpct - base) : 0;
31*a2df9606SJoseph Chen }
32*a2df9606SJoseph Chen 
33*a2df9606SJoseph Chen static int key_state_valid(int state)
34*a2df9606SJoseph Chen {
35*a2df9606SJoseph Chen 	return (state >= KEY_PRESS_NONE && state < KEY_NOT_EXIST);
36*a2df9606SJoseph Chen }
37*a2df9606SJoseph Chen 
38*a2df9606SJoseph 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 
45*a2df9606SJoseph Chen 	return ops->read(dev, code);
46b398a9a7SJoseph Chen }
47b398a9a7SJoseph Chen 
48*a2df9606SJoseph Chen int platform_key_read(int code)
496e14addfSJoseph Chen {
50*a2df9606SJoseph Chen 	struct udevice *dev;
51*a2df9606SJoseph Chen 	int report = KEY_NOT_EXIST;
526e14addfSJoseph Chen 
53*a2df9606SJoseph Chen 	for (uclass_first_device(UCLASS_KEY, &dev);
54*a2df9606SJoseph Chen 	     dev;
55*a2df9606SJoseph Chen 	     uclass_next_device(&dev)) {
56*a2df9606SJoseph Chen 		debug("key dev.name = %s, code = %d\n", dev->name, code);
57*a2df9606SJoseph Chen 		report = key_read(dev, code);
58*a2df9606SJoseph Chen 		if (key_state_valid(report)) {
59*a2df9606SJoseph Chen 			debug("key dev.name = %s, state=%d\n", dev->name, report);
60*a2df9606SJoseph Chen 			break;
61*a2df9606SJoseph Chen 		}
626e14addfSJoseph Chen 	}
636e14addfSJoseph Chen 
64*a2df9606SJoseph Chen 	return report;
656e14addfSJoseph Chen }
666e14addfSJoseph Chen 
67b398a9a7SJoseph Chen UCLASS_DRIVER(key) = {
68b398a9a7SJoseph Chen 	.id		= UCLASS_KEY,
69b398a9a7SJoseph Chen 	.name		= "key",
70b398a9a7SJoseph Chen };
71