xref: /rk3399_rockchip-uboot/drivers/input/rk8xx_pwrkey.c (revision 5ec685037a799ecdc53ecb1a12a9ed5a9cecb4f4)
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	RK816_INT_STS_REG1	0x49
18 #define	RK816_INT_MSK_REG1	0x4a
19 #define	RK816_INT_STS_REG2	0x4c
20 #define	RK816_INT_MSK_REG2	0x4d
21 #define	RK816_INT_STS_REG3	0x4e
22 #define	RK816_INT_MSK_REG3	0x4f
23 #define RK816_PWRON_RISE_INT	(1 << 6)
24 #define RK816_PWRON_FALL_INT	(1 << 5)
25 
26 #define	RK805_INT_STS_REG	0x4c
27 #define	RK805_INT_MSK_REG	0x4d
28 #define RK805_PWRON_RISE_INT	(1 << 0)
29 #define RK805_PWRON_FALL_INT	(1 << 7)
30 
31 struct key_data {
32 	u8 int_sts_reg;
33 	u8 int_msk_reg;
34 	u8 pwron_rise_int;
35 	u8 pwron_fall_int;
36 	struct reg_data *init_reg;
37 	u32 init_reg_num;
38 	struct reg_data *irq_reg;
39 	u32 irq_reg_num;
40 	uint64_t key_down_t;
41 	uint64_t key_up_t;
42 };
43 
44 struct reg_data {
45 	u8 reg;
46 	u8 val;
47 };
48 
49 static struct reg_data rk816_init_reg[] = {
50 	/* only enable rise/fall interrupt */
51 	{ RK816_INT_MSK_REG1, 0x9f },
52 	{ RK816_INT_MSK_REG2, 0xff },
53 	{ RK816_INT_MSK_REG3, 0xff },
54 	/* clear all interrupt states */
55 	{ RK816_INT_STS_REG1, 0xff },
56 	{ RK816_INT_STS_REG2, 0xff },
57 	{ RK816_INT_STS_REG3, 0xff },
58 };
59 
60 static struct reg_data rk816_irq_reg[] = {
61 	/* clear all interrupt states */
62 	{ RK816_INT_STS_REG1, 0xff },
63 	{ RK816_INT_STS_REG2, 0xff },
64 	{ RK816_INT_STS_REG3, 0xff },
65 };
66 
67 static struct reg_data rk805_irq_reg[] = {
68 	/* clear all interrupt states */
69 	{ RK805_INT_STS_REG, 0xff },
70 };
71 
72 static struct reg_data rk805_init_reg[] = {
73 	/* only enable rise/fall interrupt */
74 	{ RK805_INT_MSK_REG, 0x7e },
75 	/* clear all interrupt states */
76 	{ RK805_INT_STS_REG, 0xff },
77 };
78 
79 static inline uint64_t arch_counter_get_cntpct(void)
80 {
81 	uint64_t cval = 0;
82 
83 	isb();
84 #ifdef CONFIG_ARM64
85 	asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
86 #else
87 	asm volatile ("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
88 #endif
89 	return cval;
90 }
91 
92 static uint64_t get_ms(uint64_t base)
93 {
94 	return (arch_counter_get_cntpct() / 24000UL) - base;
95 }
96 
97 static int rk8xx_pwrkey_read(struct udevice *dev)
98 {
99 	struct key_data *key = dev_get_priv(dev);
100 	u32 report = KEY_PRESS_NONE;
101 
102 	if ((key->key_up_t > key->key_down_t) &&
103 	    (key->key_up_t - key->key_down_t) >= KEY_LONG_DOWN_MS) {
104 		debug("%s: long key ms: %llu\n", __func__, key->key_up_t - key->key_down_t);
105 		key->key_up_t = 0;
106 		key->key_down_t = 0;
107 		report = KEY_PRESS_LONG_DOWN;
108 	} else if (key->key_down_t && get_ms(key->key_down_t) >= KEY_LONG_DOWN_MS) {
109 		debug("%s: long key (hold) ms: %llu\n", __func__, key->key_up_t - key->key_down_t);
110 		key->key_up_t = 0;
111 		key->key_down_t = 0;
112 		report = KEY_PRESS_LONG_DOWN;
113 	} else if ((key->key_up_t > key->key_down_t) &&
114 		   (key->key_up_t - key->key_down_t) < KEY_LONG_DOWN_MS) {
115 		debug("%s: short key ms: %llu\n", __func__, key->key_up_t - key->key_down_t);
116 		key->key_up_t = 0;
117 		key->key_down_t = 0;
118 		report = KEY_PRESS_DOWN;
119 	} else {
120 		debug("%s: key up: %llu, down: %llu\n", __func__, key->key_up_t, key->key_down_t);
121 	}
122 
123 	return report;
124 }
125 
126 static void pwrkey_irq_handler(int irq, void *data)
127 {
128 	struct udevice *dev = data;
129 	struct key_data *key = dev_get_priv(dev);
130 	int ret, val, i;
131 
132 	/* read status */
133 	val = pmic_reg_read(dev->parent, key->int_sts_reg);
134 	if (val < 0) {
135 		printf("%s: i2c read failed, ret=%d\n", __func__, val);
136 		return;
137 	}
138 
139 	/* fall event */
140 	if (val & key->pwron_fall_int) {
141 		key->key_down_t = get_ms(0);
142 		debug("%s: key down: %llu ms\n", __func__, key->key_down_t);
143 	}
144 
145 	/* rise event */
146 	if (val & key->pwron_rise_int) {
147 		key->key_up_t = get_ms(0);
148 		debug("%s: key up: %llu ms\n", __func__, key->key_up_t);
149 	}
150 
151 	/* clear intertup */
152 	for (i = 0; i < key->irq_reg_num; i++) {
153 		ret = pmic_reg_write(dev->parent,
154 				     key->irq_reg[i].reg,
155 				     key->irq_reg[i].val);
156 		if (ret < 0) {
157 			printf("%s: i2c write reg 0x%x failed, ret=%d\n",
158 			       __func__, key->irq_reg[i].reg, ret);
159 		}
160 	}
161 }
162 
163 static int pwrkey_interrupt_init(struct udevice *dev)
164 {
165 	u32 interrupt[2], phandle;
166 	int irq, ret;
167 
168 	phandle = dev_read_u32_default(dev->parent, "interrupt-parent", -1);
169 	if (phandle < 0) {
170 		printf("failed get 'interrupt-parent', ret=%d\n", phandle);
171 		return phandle;
172 	}
173 
174 	ret = dev_read_u32_array(dev->parent, "interrupts", interrupt, 2);
175 	if (ret) {
176 		printf("failed get 'interrupt', ret=%d\n", ret);
177 		return ret;
178 	}
179 
180 	irq = phandle_gpio_to_irq(phandle, interrupt[0]);
181 	irq_install_handler(irq, pwrkey_irq_handler, dev);
182 	irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
183 	irq_handler_enable(irq);
184 
185 	return 0;
186 }
187 
188 static const struct dm_key_ops key_ops = {
189 	.type = KEY_POWER,
190 	.name = "pmic-pwrkey",
191 	.read = rk8xx_pwrkey_read,
192 };
193 
194 static int rk8xx_pwrkey_probe(struct udevice *dev)
195 {
196 	struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
197 	struct key_data *key = dev_get_priv(dev);
198 	int ret, i;
199 
200 	switch (rk8xx->variant) {
201 	case RK805_ID:
202 		key->int_sts_reg = RK805_INT_STS_REG;
203 		key->int_msk_reg = RK805_INT_MSK_REG;
204 		key->pwron_rise_int = RK805_PWRON_RISE_INT;
205 		key->pwron_fall_int = RK805_PWRON_FALL_INT;
206 		key->init_reg = rk805_init_reg;
207 		key->init_reg_num = ARRAY_SIZE(rk805_init_reg);
208 		key->irq_reg = rk805_irq_reg;
209 		key->irq_reg_num = ARRAY_SIZE(rk805_irq_reg);
210 		break;
211 
212 	case RK816_ID:
213 		key->int_sts_reg = RK816_INT_STS_REG1;
214 		key->int_msk_reg = RK816_INT_MSK_REG1;
215 		key->pwron_rise_int = RK816_PWRON_RISE_INT;
216 		key->pwron_fall_int = RK816_PWRON_FALL_INT;
217 		key->init_reg = rk816_init_reg;
218 		key->init_reg_num = ARRAY_SIZE(rk816_init_reg);
219 		key->irq_reg = rk816_irq_reg;
220 		key->irq_reg_num = ARRAY_SIZE(rk816_irq_reg);
221 		break;
222 
223 	default:
224 		return -EINVAL;
225 	}
226 
227 	/* mask and clear intertup */
228 	for (i = 0; i < key->init_reg_num; i++) {
229 		ret = pmic_reg_write(dev->parent,
230 				     key->init_reg[i].reg,
231 				     key->init_reg[i].val);
232 		if (ret < 0) {
233 			printf("%s: i2c write reg 0x%x failed, ret=%d\n",
234 			       __func__, key->init_reg[i].reg, ret);
235 			return ret;
236 		}
237 	}
238 
239 	return pwrkey_interrupt_init(dev);
240 }
241 
242 U_BOOT_DRIVER(rk8xx_pwrkey) = {
243 	.name   = "rk8xx_pwrkey",
244 	.id     = UCLASS_KEY,
245 	.probe  = rk8xx_pwrkey_probe,
246 	.ops	= &key_ops,
247 	.priv_auto_alloc_size = sizeof(struct key_data),
248 };
249