xref: /rk3399_rockchip-uboot/drivers/input/rk_key.c (revision debee64a8e8c44ca5b01d539d7d48b532dc98467)
1*debee64aSJoseph Chen /*
2*debee64aSJoseph Chen  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3*debee64aSJoseph Chen  *
4*debee64aSJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
5*debee64aSJoseph Chen  */
6*debee64aSJoseph Chen 
7*debee64aSJoseph Chen #include <dm.h>
8*debee64aSJoseph Chen #include <adc.h>
9*debee64aSJoseph Chen #include <common.h>
10*debee64aSJoseph Chen #include <console.h>
11*debee64aSJoseph Chen #include <dm.h>
12*debee64aSJoseph Chen #include <errno.h>
13*debee64aSJoseph Chen #include <fdtdec.h>
14*debee64aSJoseph Chen #include <malloc.h>
15*debee64aSJoseph Chen #include <key.h>
16*debee64aSJoseph Chen #include <linux/input.h>
17*debee64aSJoseph Chen #include <errno.h>
18*debee64aSJoseph Chen #include <dm/read.h>
19*debee64aSJoseph Chen #include <irq-generic.h>
20*debee64aSJoseph Chen #include <irq-platform.h>
21*debee64aSJoseph Chen 
22*debee64aSJoseph Chen #define ADC_MARGIN		30
23*debee64aSJoseph Chen #define MAX_KEY_NR		10
24*debee64aSJoseph Chen 
25*debee64aSJoseph Chen struct rk_key_priv {
26*debee64aSJoseph Chen 	u32 key_nr;
27*debee64aSJoseph Chen };
28*debee64aSJoseph Chen 
29*debee64aSJoseph Chen enum {
30*debee64aSJoseph Chen 	INVAL_KEY = 0,
31*debee64aSJoseph Chen 	ADC_KEY,
32*debee64aSJoseph Chen 	GPIO_KEY,
33*debee64aSJoseph Chen };
34*debee64aSJoseph Chen 
35*debee64aSJoseph Chen static void gpio_irq_handler(int irq, void *data)
36*debee64aSJoseph Chen {
37*debee64aSJoseph Chen 	struct udevice *dev = data;
38*debee64aSJoseph Chen 	struct rk_key_priv *priv = dev_get_priv(dev);
39*debee64aSJoseph Chen 	struct input_key *key = dev_get_platdata(dev);
40*debee64aSJoseph Chen 	int i;
41*debee64aSJoseph Chen 
42*debee64aSJoseph Chen 	for (i = 0; i < priv->key_nr; i++) {
43*debee64aSJoseph Chen 		if (key[i].irq != irq)
44*debee64aSJoseph Chen 			continue;
45*debee64aSJoseph Chen 
46*debee64aSJoseph Chen 		/* up event */
47*debee64aSJoseph Chen 		if (irq_get_gpio_level(irq)) {
48*debee64aSJoseph Chen 			key[i].up_t = key_get_timer(0);
49*debee64aSJoseph Chen 			debug("%s: key down: %llu ms\n",
50*debee64aSJoseph Chen 			      key[i].name, key[i].down_t);
51*debee64aSJoseph Chen 		/* down event */
52*debee64aSJoseph Chen 		} else {
53*debee64aSJoseph Chen 			key[i].down_t = key_get_timer(0);
54*debee64aSJoseph Chen 			debug("%s: key up: %llu ms\n",
55*debee64aSJoseph Chen 			      key[i].name, key[i].up_t);
56*debee64aSJoseph Chen 		}
57*debee64aSJoseph Chen 		/* Must delay */
58*debee64aSJoseph Chen 		mdelay(10);
59*debee64aSJoseph Chen 		irq_revert_irq_type(irq);
60*debee64aSJoseph Chen 	}
61*debee64aSJoseph Chen }
62*debee64aSJoseph Chen 
63*debee64aSJoseph Chen static int rk_keys_ofdata_to_platdata(struct udevice *dev)
64*debee64aSJoseph Chen {
65*debee64aSJoseph Chen 	struct rk_key_priv *priv = dev_get_priv(dev);
66*debee64aSJoseph Chen 	struct input_key *key = dev_get_platdata(dev);
67*debee64aSJoseph Chen 	u32 adc_channels[2], gpios[2], adcval, i = 0;
68*debee64aSJoseph Chen 	ofnode node;
69*debee64aSJoseph Chen 	int irq;
70*debee64aSJoseph Chen 
71*debee64aSJoseph Chen 	/* Get IO channel */
72*debee64aSJoseph Chen 	if (dev_read_u32_array(dev, "io-channels", adc_channels, 2)) {
73*debee64aSJoseph Chen 		printf("%s: failed to read 'io-channels'\n", __func__);
74*debee64aSJoseph Chen 		return -EINVAL;
75*debee64aSJoseph Chen 	}
76*debee64aSJoseph Chen 
77*debee64aSJoseph Chen 	dev_for_each_subnode(node, dev) {
78*debee64aSJoseph Chen 		/* This is an ACD key */
79*debee64aSJoseph Chen 		if (!ofnode_read_u32(node, "rockchip,adc_value", &adcval)) {
80*debee64aSJoseph Chen 			key[i].name = ofnode_read_string(node, "label");
81*debee64aSJoseph Chen 			key[i].flag = ADC_KEY;
82*debee64aSJoseph Chen 			key[i].margin = ADC_MARGIN;
83*debee64aSJoseph Chen 			key[i].value = adcval;
84*debee64aSJoseph Chen 			key[i].channel = adc_channels[1];
85*debee64aSJoseph Chen 			if (ofnode_read_u32(node, "linux,code", &key[i].code)) {
86*debee64aSJoseph Chen 				printf("%s: failed to read 'linux,code'\n",
87*debee64aSJoseph Chen 				       key[i].name);
88*debee64aSJoseph Chen 				return -EINVAL;
89*debee64aSJoseph Chen 			}
90*debee64aSJoseph Chen 		/* This is a GPIO key */
91*debee64aSJoseph Chen 		} else {
92*debee64aSJoseph Chen 			key[i].name = ofnode_read_string(node, "label");
93*debee64aSJoseph Chen 			key[i].flag = GPIO_KEY;
94*debee64aSJoseph Chen 			if (ofnode_read_u32_array(node, "gpios", gpios, 2)) {
95*debee64aSJoseph Chen 				printf("%s: failed to read 'gpios'\n",
96*debee64aSJoseph Chen 				       key[i].name);
97*debee64aSJoseph Chen 				return -EINVAL;
98*debee64aSJoseph Chen 			}
99*debee64aSJoseph Chen 			if (ofnode_read_u32(node, "linux,code", &key[i].code)) {
100*debee64aSJoseph Chen 				printf("%s: failed read 'linux,code'\n",
101*debee64aSJoseph Chen 				       key[i].name);
102*debee64aSJoseph Chen 				return -EINVAL;
103*debee64aSJoseph Chen 			}
104*debee64aSJoseph Chen 
105*debee64aSJoseph Chen 			/* Request irq */
106*debee64aSJoseph Chen 			irq = phandle_gpio_to_irq(gpios[0], gpios[1]);
107*debee64aSJoseph Chen 			if (irq < 0) {
108*debee64aSJoseph Chen 				printf("%s: failed to request irq, ret=%d\n",
109*debee64aSJoseph Chen 				       __func__, irq);
110*debee64aSJoseph Chen 				return irq;
111*debee64aSJoseph Chen 			}
112*debee64aSJoseph Chen 			key[i].irq = irq;
113*debee64aSJoseph Chen 			irq_install_handler(irq, gpio_irq_handler, dev);
114*debee64aSJoseph Chen 			irq_handler_enable(irq);
115*debee64aSJoseph Chen 			irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
116*debee64aSJoseph Chen 		}
117*debee64aSJoseph Chen 
118*debee64aSJoseph Chen 		debug("%s: name=%s: code=%d, val=%d, channel=%d, flag=%d, margin=%d\n",
119*debee64aSJoseph Chen 		      __func__, key[i].name, key[i].code, key[i].value,
120*debee64aSJoseph Chen 		      key[i].channel, key[i].flag, key[i].margin);
121*debee64aSJoseph Chen 
122*debee64aSJoseph Chen 		/* Next node */
123*debee64aSJoseph Chen 		i++;
124*debee64aSJoseph Chen 		priv->key_nr = i;
125*debee64aSJoseph Chen 		if (i >= MAX_KEY_NR) {
126*debee64aSJoseph Chen 			printf("Too many keys, Max support: %d\n", MAX_KEY_NR);
127*debee64aSJoseph Chen 			return -EINVAL;
128*debee64aSJoseph Chen 		}
129*debee64aSJoseph Chen 	}
130*debee64aSJoseph Chen 
131*debee64aSJoseph Chen 	return 0;
132*debee64aSJoseph Chen }
133*debee64aSJoseph Chen 
134*debee64aSJoseph Chen static int rk_keys_read(struct udevice *dev, int code)
135*debee64aSJoseph Chen {
136*debee64aSJoseph Chen 	struct rk_key_priv *priv = dev_get_priv(dev);
137*debee64aSJoseph Chen 	struct input_key *key = dev_get_platdata(dev);
138*debee64aSJoseph Chen 	int report = KEY_NOT_EXIST;
139*debee64aSJoseph Chen 	int max, min, i = 0;
140*debee64aSJoseph Chen 	unsigned int adcval;
141*debee64aSJoseph Chen 
142*debee64aSJoseph Chen 	for (i = 0; i < priv->key_nr; i++) {
143*debee64aSJoseph Chen 		if (key[i].code != code)
144*debee64aSJoseph Chen 			continue;
145*debee64aSJoseph Chen 
146*debee64aSJoseph Chen 		if (key[i].flag == ADC_KEY) {
147*debee64aSJoseph Chen 			if (adc_channel_single_shot("saradc",
148*debee64aSJoseph Chen 						    key[i].channel, &adcval)) {
149*debee64aSJoseph Chen 				printf("%s: failed to read saradc\n",
150*debee64aSJoseph Chen 				       key[i].name);
151*debee64aSJoseph Chen 			} else {
152*debee64aSJoseph Chen 				/* Get min, max */
153*debee64aSJoseph Chen 				max = key[i].value + key[i].margin;
154*debee64aSJoseph Chen 				if (key[i].value > key[i].margin)
155*debee64aSJoseph Chen 					min = key[i].value - key[i].margin;
156*debee64aSJoseph Chen 				else
157*debee64aSJoseph Chen 					min = key[i].value;
158*debee64aSJoseph Chen 
159*debee64aSJoseph Chen 				/* Check */
160*debee64aSJoseph Chen 				if ((adcval <= max) && (adcval >= min)) {
161*debee64aSJoseph Chen 					report = KEY_PRESS_DOWN;
162*debee64aSJoseph Chen 					printf("'%s' key pressed down\n",
163*debee64aSJoseph Chen 					       key[i].name);
164*debee64aSJoseph Chen 				} else {
165*debee64aSJoseph Chen 					report = KEY_PRESS_NONE;
166*debee64aSJoseph Chen 				}
167*debee64aSJoseph Chen 			}
168*debee64aSJoseph Chen 			break;
169*debee64aSJoseph Chen 		} else {
170*debee64aSJoseph Chen 			debug("%s: ms: %llu, up=%llu, down=%llu\n",
171*debee64aSJoseph Chen 			      key[i].name, key[i].up_t - key[i].down_t,
172*debee64aSJoseph Chen 			      key[i].up_t, key[i].down_t);
173*debee64aSJoseph Chen 
174*debee64aSJoseph Chen 			if (key[i].down_t && (key[i].up_t > key[i].down_t) &&
175*debee64aSJoseph Chen 			    (key[i].up_t - key[i].down_t) >= KEY_LONG_DOWN_MS) {
176*debee64aSJoseph Chen 				key[i].up_t = 0;
177*debee64aSJoseph Chen 				key[i].down_t = 0;
178*debee64aSJoseph Chen 				report = KEY_PRESS_LONG_DOWN;
179*debee64aSJoseph Chen 				printf("'%s' key long pressed down\n",
180*debee64aSJoseph Chen 				       key[i].name);
181*debee64aSJoseph Chen 			} else if (key[i].down_t && key_get_timer(key[i].down_t) >=
182*debee64aSJoseph Chen 				   KEY_LONG_DOWN_MS) {
183*debee64aSJoseph Chen 				key[i].up_t = 0;
184*debee64aSJoseph Chen 				key[i].down_t = 0;
185*debee64aSJoseph Chen 				report = KEY_PRESS_LONG_DOWN;
186*debee64aSJoseph Chen 				printf("'%s' key long pressed down(hold)\n",
187*debee64aSJoseph Chen 				       key[i].name);
188*debee64aSJoseph Chen 			} else if ((key[i].up_t > key[i].down_t) &&
189*debee64aSJoseph Chen 				   (key[i].up_t - key[i].down_t) < KEY_LONG_DOWN_MS) {
190*debee64aSJoseph Chen 				key[i].up_t = 0;
191*debee64aSJoseph Chen 				key[i].down_t = 0;
192*debee64aSJoseph Chen 				report = KEY_PRESS_DOWN;
193*debee64aSJoseph Chen 				printf("'%s' key pressed down\n", key[i].name);
194*debee64aSJoseph Chen 			} else {
195*debee64aSJoseph Chen 				report = KEY_PRESS_NONE;
196*debee64aSJoseph Chen 			}
197*debee64aSJoseph Chen 		}
198*debee64aSJoseph Chen 	}
199*debee64aSJoseph Chen 
200*debee64aSJoseph Chen 	return report;
201*debee64aSJoseph Chen }
202*debee64aSJoseph Chen 
203*debee64aSJoseph Chen static const struct dm_key_ops key_ops = {
204*debee64aSJoseph Chen 	.name = "rk-keys",
205*debee64aSJoseph Chen 	.read = rk_keys_read,
206*debee64aSJoseph Chen };
207*debee64aSJoseph Chen 
208*debee64aSJoseph Chen static const struct udevice_id rk_keys_ids[] = {
209*debee64aSJoseph Chen 	{ .compatible = "rockchip,key" },
210*debee64aSJoseph Chen 	{ },
211*debee64aSJoseph Chen };
212*debee64aSJoseph Chen 
213*debee64aSJoseph Chen U_BOOT_DRIVER(rk_keys) = {
214*debee64aSJoseph Chen 	.name   = "rk-keys",
215*debee64aSJoseph Chen 	.id     = UCLASS_KEY,
216*debee64aSJoseph Chen 	.ops	= &key_ops,
217*debee64aSJoseph Chen 	.of_match = rk_keys_ids,
218*debee64aSJoseph Chen 	.ofdata_to_platdata = rk_keys_ofdata_to_platdata,
219*debee64aSJoseph Chen 	.platdata_auto_alloc_size = sizeof(struct input_key) * MAX_KEY_NR,
220*debee64aSJoseph Chen 	.priv_auto_alloc_size = sizeof(struct rk_key_priv),
221*debee64aSJoseph Chen };
222