xref: /linux/drivers/mfd/rk8xx-i2c.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Rockchip RK801/RK805/RK808/RK816/RK817/RK818 Core (I2C) driver
4  *
5  * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
6  * Copyright (C) 2016 PHYTEC Messtechnik GmbH
7  *
8  * Author: Chris Zhong <zyw@rock-chips.com>
9  * Author: Zhang Qing <zhangqing@rock-chips.com>
10  * Author: Wadim Egorov <w.egorov@phytec.de>
11  */
12 
13 #include <linux/i2c.h>
14 #include <linux/mfd/rk808.h>
15 #include <linux/module.h>
16 #include <linux/of.h>
17 #include <linux/regmap.h>
18 
19 struct rk8xx_i2c_platform_data {
20 	const struct regmap_config *regmap_cfg;
21 	int variant;
22 };
23 
24 static bool rk801_is_volatile_reg(struct device *dev, unsigned int reg)
25 {
26 	switch (reg) {
27 	case RK801_SYS_STS_REG:
28 	case RK801_INT_STS0_REG:
29 	case RK801_SYS_CFG0_REG:
30 	case RK801_SYS_CFG1_REG:
31 	case RK801_SYS_CFG2_REG:
32 	case RK801_SYS_CFG3_REG:
33 	case RK801_SYS_CFG4_REG:
34 	case RK801_SLEEP_CFG_REG:
35 		return true;
36 	}
37 
38 	return false;
39 }
40 
41 static bool rk806_is_volatile_reg(struct device *dev, unsigned int reg)
42 {
43 	switch (reg) {
44 	case RK806_POWER_EN0 ... RK806_POWER_EN5:
45 	case RK806_DVS_START_CTRL ... RK806_INT_MSK1:
46 		return true;
47 	}
48 
49 	return false;
50 }
51 
52 static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
53 {
54 	/*
55 	 * Notes:
56 	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
57 	 *   we don't use that feature.  It's better to cache.
58 	 * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
59 	 *   bits are cleared in case when we shutoff anyway, but better safe.
60 	 */
61 
62 	switch (reg) {
63 	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
64 	case RK808_RTC_STATUS_REG:
65 	case RK808_VB_MON_REG:
66 	case RK808_THERMAL_REG:
67 	case RK808_DCDC_UV_STS_REG:
68 	case RK808_LDO_UV_STS_REG:
69 	case RK808_DCDC_PG_REG:
70 	case RK808_LDO_PG_REG:
71 	case RK808_DEVCTRL_REG:
72 	case RK808_INT_STS_REG1:
73 	case RK808_INT_STS_REG2:
74 		return true;
75 	}
76 
77 	return false;
78 }
79 
80 static bool rk816_is_volatile_reg(struct device *dev, unsigned int reg)
81 {
82 	/*
83 	 * Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
84 	 * we don't use that feature.  It's better to cache.
85 	 */
86 
87 	switch (reg) {
88 	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
89 	case RK808_RTC_STATUS_REG:
90 	case RK808_VB_MON_REG:
91 	case RK808_THERMAL_REG:
92 	case RK816_DCDC_EN_REG1:
93 	case RK816_DCDC_EN_REG2:
94 	case RK816_INT_STS_REG1:
95 	case RK816_INT_STS_REG2:
96 	case RK816_INT_STS_REG3:
97 	case RK808_DEVCTRL_REG:
98 	case RK816_SUP_STS_REG:
99 	case RK816_GGSTS_REG:
100 	case RK816_ZERO_CUR_ADC_REGH:
101 	case RK816_ZERO_CUR_ADC_REGL:
102 	case RK816_GASCNT_REG(0) ... RK816_BAT_VOL_REGL:
103 		return true;
104 	}
105 
106 	return false;
107 }
108 
109 static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
110 {
111 	/*
112 	 * Notes:
113 	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
114 	 *   we don't use that feature.  It's better to cache.
115 	 */
116 
117 	switch (reg) {
118 	case RK817_SECONDS_REG ... RK817_WEEKS_REG:
119 	case RK817_RTC_STATUS_REG:
120 	case RK817_CODEC_DTOP_LPT_SRST:
121 	case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
122 	case RK817_PMIC_CHRG_STS:
123 	case RK817_PMIC_CHRG_OUT:
124 	case RK817_PMIC_CHRG_IN:
125 	case RK817_INT_STS_REG0:
126 	case RK817_INT_STS_REG1:
127 	case RK817_INT_STS_REG2:
128 	case RK817_SYS_STS:
129 		return true;
130 	}
131 
132 	return false;
133 }
134 
135 
136 static const struct regmap_config rk818_regmap_config = {
137 	.reg_bits = 8,
138 	.val_bits = 8,
139 	.max_register = RK818_USB_CTRL_REG,
140 	.cache_type = REGCACHE_MAPLE,
141 	.volatile_reg = rk808_is_volatile_reg,
142 };
143 
144 static const struct regmap_config rk801_regmap_config = {
145 	.reg_bits = 8,
146 	.val_bits = 8,
147 	.max_register = RK801_SYS_CFG3_OTP_REG,
148 	.cache_type = REGCACHE_RBTREE,
149 	.volatile_reg = rk801_is_volatile_reg,
150 };
151 
152 static const struct regmap_config rk805_regmap_config = {
153 	.reg_bits = 8,
154 	.val_bits = 8,
155 	.max_register = RK805_OFF_SOURCE_REG,
156 	.cache_type = REGCACHE_MAPLE,
157 	.volatile_reg = rk808_is_volatile_reg,
158 };
159 
160 static const struct regmap_config rk806_regmap_config = {
161 	.reg_bits = 8,
162 	.val_bits = 8,
163 	.max_register = RK806_BUCK_RSERVE_REG5,
164 	.cache_type = REGCACHE_MAPLE,
165 	.volatile_reg = rk806_is_volatile_reg,
166 };
167 
168 static const struct regmap_config rk808_regmap_config = {
169 	.reg_bits = 8,
170 	.val_bits = 8,
171 	.max_register = RK808_IO_POL_REG,
172 	.cache_type = REGCACHE_MAPLE,
173 	.volatile_reg = rk808_is_volatile_reg,
174 };
175 
176 static const struct regmap_config rk816_regmap_config = {
177 	.reg_bits = 8,
178 	.val_bits = 8,
179 	.max_register = RK816_DATA_REG(18),
180 	.cache_type = REGCACHE_MAPLE,
181 	.volatile_reg = rk816_is_volatile_reg,
182 };
183 
184 static const struct regmap_config rk817_regmap_config = {
185 	.reg_bits = 8,
186 	.val_bits = 8,
187 	.max_register = RK817_GPIO_INT_CFG,
188 	.cache_type = REGCACHE_NONE,
189 	.volatile_reg = rk817_is_volatile_reg,
190 };
191 
192 static const struct rk8xx_i2c_platform_data rk801_data = {
193 	.regmap_cfg = &rk801_regmap_config,
194 	.variant = RK801_ID,
195 };
196 
197 static const struct rk8xx_i2c_platform_data rk805_data = {
198 	.regmap_cfg = &rk805_regmap_config,
199 	.variant = RK805_ID,
200 };
201 
202 static const struct rk8xx_i2c_platform_data rk806_data = {
203 	.regmap_cfg = &rk806_regmap_config,
204 	.variant = RK806_ID,
205 };
206 
207 static const struct rk8xx_i2c_platform_data rk808_data = {
208 	.regmap_cfg = &rk808_regmap_config,
209 	.variant = RK808_ID,
210 };
211 
212 static const struct rk8xx_i2c_platform_data rk809_data = {
213 	.regmap_cfg = &rk817_regmap_config,
214 	.variant = RK809_ID,
215 };
216 
217 static const struct rk8xx_i2c_platform_data rk816_data = {
218 	.regmap_cfg = &rk816_regmap_config,
219 	.variant = RK816_ID,
220 };
221 
222 static const struct rk8xx_i2c_platform_data rk817_data = {
223 	.regmap_cfg = &rk817_regmap_config,
224 	.variant = RK817_ID,
225 };
226 
227 static const struct rk8xx_i2c_platform_data rk818_data = {
228 	.regmap_cfg = &rk818_regmap_config,
229 	.variant = RK818_ID,
230 };
231 
232 static int rk8xx_i2c_probe(struct i2c_client *client)
233 {
234 	const struct rk8xx_i2c_platform_data *data;
235 	struct regmap *regmap;
236 
237 	data = device_get_match_data(&client->dev);
238 	if (!data)
239 		return -ENODEV;
240 
241 	regmap = devm_regmap_init_i2c(client, data->regmap_cfg);
242 	if (IS_ERR(regmap))
243 		return dev_err_probe(&client->dev, PTR_ERR(regmap),
244 				     "regmap initialization failed\n");
245 
246 	return rk8xx_probe(&client->dev, data->variant, client->irq, regmap);
247 }
248 
249 static void rk8xx_i2c_shutdown(struct i2c_client *client)
250 {
251 	rk8xx_shutdown(&client->dev);
252 }
253 
254 static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
255 
256 static const struct of_device_id rk8xx_i2c_of_match[] = {
257 	{ .compatible = "rockchip,rk801", .data = &rk801_data },
258 	{ .compatible = "rockchip,rk805", .data = &rk805_data },
259 	{ .compatible = "rockchip,rk806", .data = &rk806_data },
260 	{ .compatible = "rockchip,rk808", .data = &rk808_data },
261 	{ .compatible = "rockchip,rk809", .data = &rk809_data },
262 	{ .compatible = "rockchip,rk816", .data = &rk816_data },
263 	{ .compatible = "rockchip,rk817", .data = &rk817_data },
264 	{ .compatible = "rockchip,rk818", .data = &rk818_data },
265 	{ },
266 };
267 MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
268 
269 static struct i2c_driver rk8xx_i2c_driver = {
270 	.driver = {
271 		.name = "rk8xx-i2c",
272 		.of_match_table = rk8xx_i2c_of_match,
273 		.pm = &rk8xx_i2c_pm_ops,
274 	},
275 	.probe = rk8xx_i2c_probe,
276 	.shutdown  = rk8xx_i2c_shutdown,
277 };
278 module_i2c_driver(rk8xx_i2c_driver);
279 
280 MODULE_LICENSE("GPL");
281 MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
282 MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
283 MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
284 MODULE_DESCRIPTION("RK8xx I2C PMIC driver");
285