xref: /rk3399_rockchip-uboot/drivers/input/rk8xx_pwrkey.c (revision c39a6706c52f4ed2c6a025f085b614255d60e8d4)
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 <dm.h>
9 #include <key.h>
10 #include <linux/input.h>
11 #include <power/pmic.h>
12 #include <power/rk8xx_pmic.h>
13 #include <irq-generic.h>
14 #include <asm/arch/periph.h>
15 #include <dm/pinctrl.h>
16 
17 #define	RK817_INT_STS_REG0	0xf8
18 #define	RK817_INT_MSK_REG0	0xf9
19 #define	RK817_INT_STS_REG1	0xfa
20 #define	RK817_INT_MSK_REG1	0xfb
21 #define	RK817_INT_STS_REG2	0xfc
22 #define	RK817_INT_MSK_REG2	0xfd
23 #define RK817_PWRON_RISE_INT	(1 << 1)
24 #define RK817_PWRON_FALL_INT	(1 << 0)
25 #define RK817_PLUG_OUT_INT	(1 << 1)
26 
27 #define	RK816_INT_STS_REG1	0x49
28 #define	RK816_INT_MSK_REG1	0x4a
29 #define	RK816_INT_STS_REG2	0x4c
30 #define	RK816_INT_MSK_REG2	0x4d
31 #define	RK816_INT_STS_REG3	0x4e
32 #define	RK816_INT_MSK_REG3	0x4f
33 #define RK816_PWRON_RISE_INT	(1 << 6)
34 #define RK816_PWRON_FALL_INT	(1 << 5)
35 #define RK816_PLUG_OUT_INT	(1 << 1)
36 
37 #define	RK805_INT_STS_REG	0x4c
38 #define	RK805_INT_MSK_REG	0x4d
39 #define RK805_PWRON_RISE_INT	(1 << 0)
40 #define RK805_PWRON_FALL_INT	(1 << 7)
41 
42 struct rk8xx_key_priv {
43 	u8 key_int_sts_reg;
44 	u8 key_int_msk_reg;
45 	u8 plug_int_sts_reg;
46 	u8 plug_int_msk_reg;
47 	u8 pwron_rise_int;
48 	u8 pwron_fall_int;
49 	u8 plug_out_int;
50 	struct reg_data *init_reg;
51 	u32 init_reg_num;
52 	struct reg_data *irq_reg;
53 	u32 irq_reg_num;
54 };
55 
56 static struct reg_data rk817_init_reg[] = {
57 	/* only enable rise/fall interrupt, plugout */
58 	{ RK817_INT_MSK_REG0, 0xfc },
59 	{ RK817_INT_MSK_REG1, 0xfd },
60 	{ RK817_INT_MSK_REG2, 0xff },
61 	/* clear all interrupt states */
62 	{ RK817_INT_STS_REG0, 0xff },
63 	{ RK817_INT_STS_REG1, 0xff },
64 	{ RK817_INT_STS_REG2, 0xff },
65 };
66 
67 static struct reg_data rk817_irq_reg[] = {
68 	/* clear all interrupt states */
69 	{ RK817_INT_STS_REG0, 0xff },
70 	{ RK817_INT_STS_REG1, 0xff },
71 	{ RK817_INT_STS_REG2, 0xff },
72 };
73 
74 static struct reg_data rk816_init_reg[] = {
75 	/* only enable rise/fall interrupt, plugout */
76 	{ RK816_INT_MSK_REG1, 0x9f },
77 	{ RK816_INT_MSK_REG2, 0xff },
78 	{ RK816_INT_MSK_REG3, 0xfd },
79 	/* clear all interrupt states */
80 	{ RK816_INT_STS_REG1, 0xff },
81 	{ RK816_INT_STS_REG2, 0xff },
82 	{ RK816_INT_STS_REG3, 0xff },
83 };
84 
85 static struct reg_data rk816_irq_reg[] = {
86 	/* clear all interrupt states */
87 	{ RK816_INT_STS_REG1, 0xff },
88 	{ RK816_INT_STS_REG2, 0xff },
89 	{ RK816_INT_STS_REG3, 0xff },
90 };
91 
92 static struct reg_data rk805_irq_reg[] = {
93 	/* clear all interrupt states */
94 	{ RK805_INT_STS_REG, 0xff },
95 };
96 
97 static struct reg_data rk805_init_reg[] = {
98 	/* only enable rise/fall interrupt */
99 	{ RK805_INT_MSK_REG, 0x7e },
100 	/* clear all interrupt states */
101 	{ RK805_INT_STS_REG, 0xff },
102 };
103 
104 static int rk8xx_pwrkey_read(struct udevice *dev, int code)
105 {
106 	struct input_key *key = dev_get_platdata(dev);
107 	u32 report = KEY_NOT_EXIST;
108 
109 	if (key->code != code)
110 		goto out;
111 
112 	debug("%s: long key ms: %llu\n",
113 	      __func__, key->up_t - key->down_t);
114 
115 	if ((key->up_t > key->down_t) &&
116 	    (key->up_t - key->down_t) >= KEY_LONG_DOWN_MS) {
117 		key->up_t = 0;
118 		key->down_t = 0;
119 		report = KEY_PRESS_LONG_DOWN;
120 		printf("'%s' key long pressed down\n", key->name);
121 	} else if (key->down_t &&
122 		   key_get_timer(key->down_t) >= KEY_LONG_DOWN_MS) {
123 		key->up_t = 0;
124 		key->down_t = 0;
125 		report = KEY_PRESS_LONG_DOWN;
126 		printf("'%s' key long pressed down(hold)\n", key->name);
127 	} else if ((key->up_t > key->down_t) &&
128 		   (key->up_t - key->down_t) < KEY_LONG_DOWN_MS) {
129 		key->up_t = 0;
130 		key->down_t = 0;
131 		report = KEY_PRESS_DOWN;
132 		printf("'%s' key pressed down\n", key->name);
133 	} else {
134 		report = KEY_PRESS_NONE;
135 	}
136 
137 out:
138 	return report;
139 }
140 
141 static void pwrkey_irq_handler(int irq, void *data)
142 {
143 	struct udevice *dev = data;
144 	struct rk8xx_key_priv *priv = dev_get_priv(dev);
145 	struct input_key *key = dev_get_platdata(dev);
146 	int ret, val, i;
147 
148 	debug("%s: irq = %d\n", __func__, irq);
149 
150 	/*
151 	 * This plug out interrupt only used to wakeup cpu while U-Boot
152 	 * charging and system suspend. Because we need to detect charger
153 	 * plug out event and then shutdown system.
154 	 */
155 	if (priv->plug_int_sts_reg) {
156 		val = pmic_reg_read(dev->parent, priv->plug_int_sts_reg);
157 		if (val < 0) {
158 			printf("%s: i2c read failed, ret=%d\n", __func__, val);
159 			return;
160 		}
161 
162 		if (val & priv->plug_out_int)
163 			printf("Plug out interrupt\n");
164 	}
165 
166 	/* read key status */
167 	val = pmic_reg_read(dev->parent, priv->key_int_sts_reg);
168 	if (val < 0) {
169 		printf("%s: i2c read failed, ret=%d\n", __func__, val);
170 		return;
171 	}
172 
173 	/* fall event */
174 	if (val & priv->pwron_fall_int) {
175 		key->down_t = key_get_timer(0);
176 		debug("%s: key down: %llu ms\n", __func__, key->down_t);
177 	}
178 
179 	/* rise event */
180 	if (val & priv->pwron_rise_int) {
181 		key->up_t = key_get_timer(0);
182 		debug("%s: key up: %llu ms\n", __func__, key->up_t);
183 	}
184 
185 	/* clear intertup */
186 	for (i = 0; i < priv->irq_reg_num; i++) {
187 		ret = pmic_reg_write(dev->parent,
188 				     priv->irq_reg[i].reg,
189 				     priv->irq_reg[i].val);
190 		if (ret < 0) {
191 			printf("%s: i2c write reg 0x%x failed, ret=%d\n",
192 			       __func__, priv->irq_reg[i].reg, ret);
193 		}
194 
195 		debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->irq_reg[i].reg,
196 		      pmic_reg_read(dev->parent, priv->irq_reg[i].reg));
197 	}
198 }
199 
200 static int pwrkey_interrupt_init(struct udevice *dev)
201 {
202 	struct input_key *key = dev_get_platdata(dev);
203 	u32 interrupt[2], phandle;
204 	int irq, ret;
205 
206 	phandle = dev_read_u32_default(dev->parent, "interrupt-parent", -1);
207 	if (phandle < 0) {
208 		printf("failed get 'interrupt-parent', ret=%d\n", phandle);
209 		return phandle;
210 	}
211 
212 	ret = dev_read_u32_array(dev->parent, "interrupts", interrupt, 2);
213 	if (ret) {
214 		printf("failed get 'interrupt', ret=%d\n", ret);
215 		return ret;
216 	}
217 
218 	key->name = "pwrkey";
219 	key->code = KEY_POWER;
220 	irq = phandle_gpio_to_irq(phandle, interrupt[0]);
221 	irq_install_handler(irq, pwrkey_irq_handler, dev);
222 	irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
223 	irq_handler_enable(irq);
224 
225 	return 0;
226 }
227 
228 static const struct dm_key_ops key_ops = {
229 	.name = "rk8xx-pwrkey",
230 	.read = rk8xx_pwrkey_read,
231 };
232 
233 static int rk8xx_pwrkey_probe(struct udevice *dev)
234 {
235 	struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
236 	struct rk8xx_key_priv *priv = dev_get_priv(dev);
237 	int ret, i;
238 
239 	switch (rk8xx->variant) {
240 	case RK805_ID:
241 		priv->key_int_sts_reg = RK805_INT_STS_REG;
242 		priv->key_int_msk_reg = RK805_INT_MSK_REG;
243 		priv->pwron_rise_int = RK805_PWRON_RISE_INT;
244 		priv->pwron_fall_int = RK805_PWRON_FALL_INT;
245 		priv->init_reg = rk805_init_reg;
246 		priv->init_reg_num = ARRAY_SIZE(rk805_init_reg);
247 		priv->irq_reg = rk805_irq_reg;
248 		priv->irq_reg_num = ARRAY_SIZE(rk805_irq_reg);
249 		break;
250 
251 	case RK816_ID:
252 		priv->key_int_sts_reg = RK816_INT_STS_REG1;
253 		priv->key_int_msk_reg = RK816_INT_MSK_REG1;
254 		priv->plug_int_sts_reg = RK816_INT_STS_REG3;
255 		priv->plug_int_msk_reg = RK816_INT_MSK_REG3;
256 		priv->pwron_rise_int = RK816_PWRON_RISE_INT;
257 		priv->pwron_fall_int = RK816_PWRON_FALL_INT;
258 		priv->plug_out_int = RK816_PLUG_OUT_INT;
259 		priv->init_reg = rk816_init_reg;
260 		priv->init_reg_num = ARRAY_SIZE(rk816_init_reg);
261 		priv->irq_reg = rk816_irq_reg;
262 		priv->irq_reg_num = ARRAY_SIZE(rk816_irq_reg);
263 		break;
264 	case RK809_ID:
265 	case RK817_ID:
266 		priv->key_int_sts_reg = RK817_INT_STS_REG0;
267 		priv->key_int_msk_reg = RK817_INT_MSK_REG0;
268 		priv->plug_int_sts_reg = RK817_INT_STS_REG1;
269 		priv->plug_int_msk_reg = RK817_INT_MSK_REG1;
270 		priv->pwron_rise_int = RK817_PWRON_RISE_INT;
271 		priv->pwron_fall_int = RK817_PWRON_FALL_INT;
272 		priv->plug_out_int = RK817_PLUG_OUT_INT;
273 		priv->init_reg = rk817_init_reg;
274 		priv->init_reg_num = ARRAY_SIZE(rk817_init_reg);
275 		priv->irq_reg = rk817_irq_reg;
276 		priv->irq_reg_num = ARRAY_SIZE(rk817_irq_reg);
277 		break;
278 	default:
279 		return -EINVAL;
280 	}
281 
282 	/* mask and clear interrupt */
283 	for (i = 0; i < priv->init_reg_num; i++) {
284 		ret = pmic_reg_write(dev->parent,
285 				     priv->init_reg[i].reg,
286 				     priv->init_reg[i].val);
287 		if (ret < 0) {
288 			printf("%s: i2c write reg 0x%x failed, ret=%d\n",
289 			       __func__, priv->init_reg[i].reg, ret);
290 			return ret;
291 		}
292 
293 		debug("%s: reg[%x] = 0x%x\n", __func__, priv->init_reg[i].reg,
294 		      pmic_reg_read(dev->parent, priv->init_reg[i].reg));
295 	}
296 
297 	return pwrkey_interrupt_init(dev);
298 }
299 
300 U_BOOT_DRIVER(rk8xx_pwrkey) = {
301 	.name   = "rk8xx_pwrkey",
302 	.id     = UCLASS_KEY,
303 	.ops	= &key_ops,
304 	.probe  = rk8xx_pwrkey_probe,
305 	.platdata_auto_alloc_size = sizeof(struct input_key),
306 	.priv_auto_alloc_size = sizeof(struct rk8xx_key_priv),
307 };
308