xref: /rk3399_rockchip-uboot/drivers/input/key-uclass.c (revision d8db5367cf2573bd2878866cf70446102183652c)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <adc.h>
9 #include <dm.h>
10 #include <key.h>
11 #include <dm/lists.h>
12 #include <irq-generic.h>
13 
14 #define KEY_WARN(fmt, args...)	printf("Key Warn: "fmt, ##args)
15 #define KEY_ERR(fmt, args...)	printf("Key Error: "fmt, ##args)
16 #define KEY_DBG(fmt, args...)	 debug("Key Debug: "fmt, ##args)
17 
18 static inline uint64_t arch_counter_get_cntpct(void)
19 {
20 	uint64_t cval = 0;
21 
22 	isb();
23 #ifdef CONFIG_ARM64
24 	asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
25 #else
26 	asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
27 #endif
28 	return cval;
29 }
30 
31 uint64_t key_timer(uint64_t base)
32 {
33 	uint64_t cntpct;
34 
35 	cntpct = arch_counter_get_cntpct() / 24000UL;
36 	return (cntpct > base) ? (cntpct - base) : 0;
37 }
38 
39 static int key_adc_event(struct dm_key_uclass_platdata *uc_key, int adcval)
40 {
41 	return (adcval <= uc_key->max && adcval >= uc_key->min) ?
42 		KEY_PRESS_DOWN : KEY_PRESS_NONE;
43 }
44 
45 static int key_gpio_event(struct dm_key_uclass_platdata *uc_key)
46 {
47 	if (!dm_gpio_is_valid(&uc_key->gpio)) {
48 		KEY_ERR("'%s' Invalid gpio\n", uc_key->name);
49 		return KEY_PRESS_NONE;
50 	}
51 
52 	return dm_gpio_get_value(&uc_key->gpio) ?
53 	       KEY_PRESS_DOWN : KEY_PRESS_NONE;
54 }
55 
56 static int key_gpio_interrupt_event(struct dm_key_uclass_platdata *uc_key)
57 {
58 	int event;
59 
60 	debug("%s: %s: up=%llu, down=%llu, delta=%llu\n",
61 	      __func__, uc_key->name, uc_key->rise_ms, uc_key->fall_ms,
62 	      uc_key->rise_ms - uc_key->fall_ms);
63 
64 	/* Possible this is machine power-on long pressed, so ignore this */
65 	if (uc_key->fall_ms == 0 && uc_key->rise_ms != 0) {
66 		event = KEY_PRESS_NONE;
67 		goto out;
68 	}
69 
70 	if ((uc_key->rise_ms > uc_key->fall_ms) &&
71 	    (uc_key->rise_ms - uc_key->fall_ms) >= KEY_LONG_DOWN_MS) {
72 		uc_key->rise_ms = 0;
73 		uc_key->fall_ms = 0;
74 		event = KEY_PRESS_LONG_DOWN;
75 		KEY_DBG("%s key long pressed..\n", uc_key->name);
76 	} else if (uc_key->fall_ms &&
77 		   key_timer(uc_key->fall_ms) >= KEY_LONG_DOWN_MS) {
78 		uc_key->rise_ms = 0;
79 		uc_key->fall_ms = 0;
80 		event = KEY_PRESS_LONG_DOWN;
81 		KEY_DBG("%s key long pressed(hold)..\n", uc_key->name);
82 	} else if ((uc_key->rise_ms > uc_key->fall_ms) &&
83 		   (uc_key->rise_ms - uc_key->fall_ms) < KEY_LONG_DOWN_MS) {
84 		uc_key->rise_ms = 0;
85 		uc_key->fall_ms = 0;
86 		event = KEY_PRESS_DOWN;
87 		KEY_DBG("%s key short pressed..\n", uc_key->name);
88 	/* Possible in charge animation, we enable irq after fuel gauge updated */
89 	} else if (uc_key->rise_ms && uc_key->fall_ms &&
90 		   (uc_key->rise_ms == uc_key->fall_ms)) {
91 		uc_key->rise_ms = 0;
92 		uc_key->fall_ms = 0;
93 		event = KEY_PRESS_DOWN;
94 		KEY_DBG("%s key short pressed..\n", uc_key->name);
95 	} else {
96 		event = KEY_PRESS_NONE;
97 	}
98 
99 out:
100 	return event;
101 }
102 
103 int key_is_pressed(int event)
104 {
105 	return (event == KEY_PRESS_DOWN || event == KEY_PRESS_LONG_DOWN);
106 }
107 
108 static int key_core_read(struct dm_key_uclass_platdata *uc_key)
109 {
110 	unsigned int adcval;
111 
112 	if (uc_key->type == ADC_KEY) {
113 		if (adc_channel_single_shot("saradc",
114 					    uc_key->channel, &adcval)) {
115 			KEY_ERR("%s failed to read saradc\n", uc_key->name);
116 			return KEY_NOT_EXIST;
117 		}
118 
119 		return key_adc_event(uc_key, adcval);
120 	}
121 
122 	return (uc_key->code == KEY_POWER) ?
123 		key_gpio_interrupt_event(uc_key) :
124 		key_gpio_event(uc_key);
125 }
126 
127 int key_read(int code)
128 {
129 	struct dm_key_uclass_platdata *uc_key;
130 	struct udevice *dev;
131 	struct uclass *uc;
132 	bool allow_pre_reloc = false;
133 	int ret, event = KEY_NOT_EXIST;
134 
135 	ret = uclass_get(UCLASS_KEY, &uc);
136 	if (ret)
137 		return ret;
138 
139 try_again:
140 	for (uclass_first_device(UCLASS_KEY, &dev);
141 	     dev;
142 	     uclass_next_device(&dev)) {
143 		uc_key = dev_get_uclass_platdata(dev);
144 
145 		if (!allow_pre_reloc && uc_key->pre_reloc)
146 			continue;
147 
148 		if (uc_key->code != code)
149 			continue;
150 
151 		event = key_core_read(uc_key);
152 		if (key_is_pressed(event))
153 			return event;
154 	}
155 
156 	/* If not find valid key node from kernel, try from u-boot */
157 	if (event == KEY_NOT_EXIST && !allow_pre_reloc) {
158 		allow_pre_reloc = true;
159 		goto try_again;
160 	}
161 
162 	return event;
163 }
164 
165 #if CONFIG_IS_ENABLED(IRQ)
166 #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \
167 		(CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0)
168 static void power_key_download(struct dm_key_uclass_platdata *uc_key)
169 {
170 	int trig_cnt = CONFIG_PWRKEY_DNL_TRIGGER_NUM;
171 	static u64 old_rise_ms;
172 
173 	if (uc_key->code == KEY_POWER && old_rise_ms != uc_key->rise_ms) {
174 		old_rise_ms = uc_key->rise_ms;
175 		uc_key->trig_cnt++;
176 		if (uc_key->trig_cnt >= trig_cnt) {
177 			printf("\nEnter download mode by pwrkey\n");
178 			irq_handler_disable(uc_key->irq);
179 			run_command("rockusb 0 $devtype $devnum", 0);
180 			run_command("rbrom", 0);
181 		}
182 	}
183 }
184 
185 int pwrkey_download_init(void)
186 {
187 	return (KEY_NOT_EXIST == key_read(KEY_POWER));
188 }
189 #endif
190 
191 static void gpio_irq_handler(int irq, void *data)
192 {
193 	struct udevice *dev = data;
194 	struct dm_key_uclass_platdata *uc_key = dev_get_uclass_platdata(dev);
195 
196 	if (uc_key->irq != irq)
197 		return;
198 
199 	if (uc_key->irq_thread) {
200 		uc_key->irq_thread(irq, data);
201 	} else {
202 		if (irq_get_gpio_level(irq)) {
203 			uc_key->rise_ms = key_timer(0);
204 			KEY_DBG("%s: key dn: %llu ms\n",
205 				uc_key->name, uc_key->fall_ms);
206 		} else {
207 			uc_key->fall_ms = key_timer(0);
208 			KEY_DBG("%s: key up: %llu ms\n",
209 				uc_key->name, uc_key->rise_ms);
210 		}
211 
212 		/* Must delay */
213 		mdelay(10);
214 		irq_revert_irq_type(irq);
215 	}
216 
217 	/* Hook event: enter download mode by pwrkey */
218 #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \
219 		(CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0)
220 	power_key_download(uc_key);
221 #endif
222 }
223 #endif
224 
225 int key_bind_children(struct udevice *dev, const char *drv_name)
226 {
227 	const char *name;
228 	ofnode node;
229 	int ret;
230 
231 	dev_for_each_subnode(node, dev) {
232 		/*
233 		 * If this node has "compatible" property, this is not
234 		 * a amp subnode, but a normal device. skip.
235 		 */
236 		ofnode_get_property(node, "compatible", &ret);
237 		if (ret >= 0)
238 			continue;
239 
240 		if (ret != -FDT_ERR_NOTFOUND)
241 			return ret;
242 
243 		name = ofnode_get_name(node);
244 		if (!name)
245 			return -EINVAL;
246 		ret = device_bind_driver_to_node(dev, drv_name, name,
247 						 node, NULL);
248 		if (ret)
249 			return ret;
250 	}
251 
252 	return 0;
253 }
254 
255 static int key_post_probe(struct udevice *dev)
256 {
257 	struct dm_key_uclass_platdata *uc_key;
258 	int ret;
259 #ifdef CONFIG_SARADC_ROCKCHIP_V2
260 	int margin = 120;
261 #else
262 	int margin = 30;
263 #endif
264 	uc_key = dev_get_uclass_platdata(dev);
265 	if (!uc_key)
266 		return -ENXIO;
267 
268 	/* True from U-Boot key node */
269 	uc_key->pre_reloc = dev_read_bool(dev, "u-boot,dm-pre-reloc") ||
270 			    dev_read_bool(dev, "u-boot,dm-spl");
271 
272 	if (uc_key->type == ADC_KEY) {
273 		uc_key->max = uc_key->adcval + margin;
274 		uc_key->min = uc_key->adcval > margin ?
275 					uc_key->adcval - margin : 0;
276 	} else {
277 		if (uc_key->code == KEY_POWER) {
278 #if CONFIG_IS_ENABLED(IRQ)
279 			int irq;
280 
281 			if (uc_key->skip_irq_init)
282 				return 0;
283 
284 			irq = phandle_gpio_to_irq(uc_key->gpios[0],
285 						  uc_key->gpios[1]);
286 			if (irq < 0) {
287 				KEY_ERR("%s: failed to request irq, ret=%d\n",
288 					uc_key->name, irq);
289 				return irq;
290 			}
291 
292 			if (uc_key->code != KEY_POWER && uc_key->irq_thread) {
293 				KEY_WARN("%s: only power key can request irq thread\n",
294 					 uc_key->name);
295 				return -EINVAL;
296 			}
297 
298 			uc_key->irq = irq;
299 			irq_install_handler(irq, gpio_irq_handler, dev);
300 			irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
301 			irq_handler_enable(irq);
302 #else
303 			KEY_WARN("%s: no IRQ framework available\n", uc_key->name);
304 #endif
305 		} else {
306 			ret = gpio_request_by_name(dev, "gpios", 0,
307 						   &uc_key->gpio, GPIOD_IS_IN);
308 			if (ret) {
309 				KEY_ERR("%s: failed to request gpio, ret=%d\n",
310 					uc_key->name, ret);
311 				return ret;
312 			}
313 		}
314 	}
315 
316 #ifdef DEBUG
317 	printf("[%s] (%s, %s, %s):\n", uc_key->name,
318 	       uc_key->type == ADC_KEY ? "ADC" : "GPIO",
319 	       uc_key->pre_reloc ? "U-Boot" : "Kernel",
320 	       dev->parent->name);
321 
322 	if (uc_key->type == ADC_KEY) {
323 		printf("    adcval: %d (%d, %d)\n", uc_key->adcval,
324 		       uc_key->min, uc_key->max);
325 		printf("   channel: %d\n\n", uc_key->channel);
326 	} else {
327 		const char *gpio_name =
328 		     ofnode_get_name(ofnode_get_by_phandle(uc_key->gpios[0]));
329 
330 		printf("       irq: %d\n", uc_key->irq);
331 		printf("   gpio[0]: %s\n", gpio_name);
332 		printf("   gpio[1]: %d\n\n", uc_key->gpios[1]);
333 	}
334 #endif
335 
336 	return 0;
337 }
338 
339 UCLASS_DRIVER(key) = {
340 	.id		= UCLASS_KEY,
341 	.name		= "key",
342 	.post_probe	= key_post_probe,
343 	.per_device_platdata_auto_alloc_size =
344 			sizeof(struct dm_key_uclass_platdata),
345 };
346