xref: /rk3399_rockchip-uboot/drivers/input/rk8xx_pwrkey.c (revision befbd723c2c9eadcfa6e9ae1dca845f05d3c29c8)
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 <power/pmic.h>
11 #include <power/rk8xx_pmic.h>
12 
13 #define	RK816_INT_STS_REG1	0x49
14 #define	RK816_INT_MSK_REG1	0x4a
15 #define RK816_PWRON_RISE_INT	(1 << 6)
16 #define RK816_PWRON_FALL_INT	(1 << 5)
17 
18 #define	RK805_INT_STS_REG	0x4c
19 #define	RK805_INT_MSK_REG	0x4d
20 #define RK805_PWRON_RISE_INT	(1 << 0)
21 #define RK805_PWRON_FALL_INT	(1 << 7)
22 
23 struct key_data {
24 	u8 int_sts_reg;
25 	u8 int_msk_reg;
26 	u8 pwron_rise_int;
27 	u8 pwron_fall_int;
28 };
29 
30 static int rk8xx_pwrkey_read(struct udevice *dev)
31 {
32 	struct key_data *key = dev_get_priv(dev);
33 	int status = KEY_PRESS_NONE;
34 	int ret, val;
35 
36 	val = pmic_reg_read(dev->parent, key->int_sts_reg);
37 	if (val < 0) {
38 		printf("%s: i2c read failed, ret=%d\n", __func__, val);
39 		return val;
40 	}
41 
42 	if (val & key->pwron_fall_int) {
43 		/* Clear rise when detect fall */
44 		ret = pmic_reg_write(dev->parent, key->int_sts_reg,
45 				     key->pwron_rise_int);
46 		if (ret < 0) {
47 			printf("%s: i2c write failed, ret=%d\n", __func__, val);
48 			return ret;
49 		}
50 
51 		status = KEY_PRESS_DOWN;
52 	}
53 
54 	/* Must check pwron rise behind of fall !! */
55 	if (val & key->pwron_rise_int) {
56 		/* Clear fall when detect rise */
57 		ret = pmic_reg_write(dev->parent, key->int_sts_reg,
58 				     key->pwron_fall_int);
59 		if (ret < 0) {
60 			printf("%s: i2c write failed, ret=%d\n", __func__, val);
61 			return ret;
62 		}
63 
64 		status = KEY_PRESS_UP;
65 	}
66 
67 	return status;
68 }
69 
70 static const struct dm_key_ops key_ops = {
71 	.read = rk8xx_pwrkey_read,
72 };
73 
74 static int rk8xx_pwrkey_probe(struct udevice *dev)
75 {
76 	struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
77 	struct key_data *key = dev_get_priv(dev);
78 	int ret, val;
79 
80 	switch (rk8xx->variant) {
81 	case RK805_ID:
82 		key->int_sts_reg = RK805_INT_STS_REG;
83 		key->int_msk_reg = RK805_INT_MSK_REG;
84 		key->pwron_rise_int = RK805_PWRON_RISE_INT;
85 		key->pwron_fall_int = RK805_PWRON_FALL_INT;
86 		break;
87 
88 	case RK816_ID:
89 		key->int_sts_reg = RK816_INT_STS_REG1;
90 		key->int_msk_reg = RK816_INT_MSK_REG1;
91 		key->pwron_rise_int = RK816_PWRON_RISE_INT;
92 		key->pwron_fall_int = RK816_PWRON_FALL_INT;
93 		break;
94 
95 	default:
96 		return -EINVAL;
97 	}
98 
99 	/* Clear states */
100 	ret = pmic_reg_write(dev->parent, key->int_sts_reg,
101 			     key->pwron_rise_int | key->pwron_fall_int);
102 	if (ret < 0) {
103 		printf("%s: i2c write failed, ret=%d\n", __func__, ret);
104 		return ret;
105 	}
106 
107 	val = pmic_reg_read(dev->parent, key->int_msk_reg);
108 	if (val < 0) {
109 		printf("%s: i2c read failed, ret=%d\n", __func__, val);
110 		return val;
111 	}
112 
113 	/* enable fall and rise interrupt */
114 	val &= ~(key->pwron_rise_int | key->pwron_fall_int);
115 	ret = pmic_reg_write(dev->parent, key->int_msk_reg, val);
116 	if (ret < 0) {
117 		printf("%s: i2c write failed, ret=%d\n", __func__, val);
118 		return ret;
119 	}
120 
121 	return 0;
122 }
123 
124 U_BOOT_DRIVER(rk8xx_pwrkey) = {
125 	.name   = "rk8xx_pwrkey",
126 	.id     = UCLASS_KEY,
127 	.probe  = rk8xx_pwrkey_probe,
128 	.ops	= &key_ops,
129 	.priv_auto_alloc_size = sizeof(struct key_data),
130 };
131