xref: /rk3399_rockchip-uboot/drivers/input/gpio_key.c (revision 5c47e3d4734d329f41880f3b6ccf76f598763980)
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 <adc.h>
9 #include <common.h>
10 #include <console.h>
11 #include <dm.h>
12 #include <errno.h>
13 #include <fdtdec.h>
14 #include <malloc.h>
15 #include <key.h>
16 #include <linux/input.h>
17 #include <errno.h>
18 #include <dm/read.h>
19 #include <irq-generic.h>
20 #include <irq-platform.h>
21 
22 #define MAX_KEY_NR	10
23 
24 struct gpio_key_priv {
25 	u32 key_nr;
26 };
27 
28 static void gpio_irq_handler(int irq, void *data)
29 {
30 	struct udevice *dev = data;
31 	struct gpio_key_priv *priv = dev_get_priv(dev);
32 	struct input_key *key = dev_get_platdata(dev);
33 	int i;
34 
35 	for (i = 0; i < priv->key_nr; i++) {
36 		if (key[i].irq != irq)
37 			continue;
38 
39 		/* up event */
40 		if (irq_get_gpio_level(irq)) {
41 			key[i].up_t = key_get_timer(0);
42 			debug("%s: key down: %llu ms\n",
43 			      key[i].name, key[i].down_t);
44 		/* down event */
45 		} else {
46 			key[i].down_t = key_get_timer(0);
47 			debug("%s: key up: %llu ms\n",
48 			      key[i].name, key[i].up_t);
49 		}
50 		/* Must delay */
51 		mdelay(10);
52 		irq_revert_irq_type(irq);
53 	}
54 }
55 
56 static int gpio_key_ofdata_to_platdata(struct udevice *dev)
57 {
58 	struct gpio_key_priv *priv = dev_get_priv(dev);
59 	struct input_key *key = dev_get_platdata(dev);
60 	u32 gpios[2], i = 0;
61 	ofnode node;
62 	int irq;
63 
64 	dev_for_each_subnode(node, dev) {
65 		key[i].name = ofnode_read_string(node, "label");
66 		if (ofnode_read_u32(node, "linux,code", &key[i].code)) {
67 			printf("failed read 'linux,code' of %s key\n",
68 			       key[i].name);
69 			return -EINVAL;
70 		}
71 		if (ofnode_read_u32_array(node, "gpios", gpios, 2)) {
72 			printf("failed to read 'gpios' of %s key\n",
73 			       key[i].name);
74 			return -EINVAL;
75 		}
76 
77 		/* Must register as interrupt, be able to wakeup system */
78 		irq = phandle_gpio_to_irq(gpios[0], gpios[1]);
79 		if (irq < 0) {
80 			printf("failed to request irq for gpio, ret=%d\n", irq);
81 			return irq;
82 		}
83 		key[i].irq = irq;
84 		irq_install_handler(irq, gpio_irq_handler, dev);
85 		irq_handler_enable(irq);
86 		irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
87 
88 		debug("%s: name=%s: code=%d\n",
89 		      __func__, key[i].name, key[i].code);
90 
91 		/* Next node */
92 		i++;
93 		priv->key_nr = i;
94 		if (i >= MAX_KEY_NR) {
95 			printf("Too many keys, Max support: %d\n", MAX_KEY_NR);
96 			return -EINVAL;
97 		}
98 	}
99 
100 	return 0;
101 }
102 
103 static int gpio_key_read(struct udevice *dev, int code)
104 {
105 	struct gpio_key_priv *priv = dev_get_priv(dev);
106 	struct input_key *key = dev_get_platdata(dev);
107 	u32 report = KEY_NOT_EXIST;
108 	int i = 0;
109 
110 	for (i = 0; i < priv->key_nr; i++) {
111 		if (key[i].code != code)
112 			continue;
113 
114 		debug("%s: long key ms: %llu, up=%llu, down=%llu\n",
115 		      key[i].name, key[i].up_t - key[i].down_t,
116 		      key[i].up_t, key[i].down_t);
117 
118 		if (key[i].down_t && (key[i].up_t > key[i].down_t) &&
119 		    (key[i].up_t - key[i].down_t) >= KEY_LONG_DOWN_MS) {
120 			key[i].up_t = 0;
121 			key[i].down_t = 0;
122 			report = KEY_PRESS_LONG_DOWN;
123 			printf("'%s' key long pressed down\n", key[i].name);
124 		} else if (key[i].down_t && key_get_timer(key[i].down_t) >=
125 			   KEY_LONG_DOWN_MS) {
126 			key[i].up_t = 0;
127 			key[i].down_t = 0;
128 			report = KEY_PRESS_LONG_DOWN;
129 			printf("'%s' key long pressed down(hold)\n",
130 			       key[i].name);
131 		} else if ((key[i].up_t > key[i].down_t) &&
132 			   (key[i].up_t - key[i].down_t) < KEY_LONG_DOWN_MS) {
133 			key[i].up_t = 0;
134 			key[i].down_t = 0;
135 			report = KEY_PRESS_DOWN;
136 			printf("'%s' key pressed down\n", key[i].name);
137 		} else {
138 			report = KEY_PRESS_NONE;
139 		}
140 	}
141 
142 	return report;
143 }
144 
145 static const struct dm_key_ops key_ops = {
146 	.name = "gpio-keys",
147 	.read = gpio_key_read,
148 };
149 
150 static const struct udevice_id gpio_key_ids[] = {
151 	{ .compatible = "gpio-keys" },
152 	{ },
153 };
154 
155 U_BOOT_DRIVER(gpio_keys) = {
156 	.name   = "gpio-keys",
157 	.id     = UCLASS_KEY,
158 	.of_match = gpio_key_ids,
159 	.ops	= &key_ops,
160 	.ofdata_to_platdata = gpio_key_ofdata_to_platdata,
161 	.platdata_auto_alloc_size = sizeof(struct input_key) * MAX_KEY_NR,
162 	.priv_auto_alloc_size = sizeof(struct gpio_key_priv),
163 };
164