xref: /linux/drivers/mfd/rk8xx-i2c.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Rockchip 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 rk808_is_volatile_reg(struct device *dev, unsigned int reg)
25 {
26 	/*
27 	 * Notes:
28 	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
29 	 *   we don't use that feature.  It's better to cache.
30 	 * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
31 	 *   bits are cleared in case when we shutoff anyway, but better safe.
32 	 */
33 
34 	switch (reg) {
35 	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
36 	case RK808_RTC_STATUS_REG:
37 	case RK808_VB_MON_REG:
38 	case RK808_THERMAL_REG:
39 	case RK808_DCDC_UV_STS_REG:
40 	case RK808_LDO_UV_STS_REG:
41 	case RK808_DCDC_PG_REG:
42 	case RK808_LDO_PG_REG:
43 	case RK808_DEVCTRL_REG:
44 	case RK808_INT_STS_REG1:
45 	case RK808_INT_STS_REG2:
46 		return true;
47 	}
48 
49 	return false;
50 }
51 
52 static bool rk816_is_volatile_reg(struct device *dev, unsigned int reg)
53 {
54 	/*
55 	 * Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
56 	 * we don't use that feature.  It's better to cache.
57 	 */
58 
59 	switch (reg) {
60 	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
61 	case RK808_RTC_STATUS_REG:
62 	case RK808_VB_MON_REG:
63 	case RK808_THERMAL_REG:
64 	case RK816_DCDC_EN_REG1:
65 	case RK816_DCDC_EN_REG2:
66 	case RK816_INT_STS_REG1:
67 	case RK816_INT_STS_REG2:
68 	case RK816_INT_STS_REG3:
69 	case RK808_DEVCTRL_REG:
70 	case RK816_SUP_STS_REG:
71 	case RK816_GGSTS_REG:
72 	case RK816_ZERO_CUR_ADC_REGH:
73 	case RK816_ZERO_CUR_ADC_REGL:
74 	case RK816_GASCNT_REG(0) ... RK816_BAT_VOL_REGL:
75 		return true;
76 	}
77 
78 	return false;
79 }
80 
81 static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
82 {
83 	/*
84 	 * Notes:
85 	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
86 	 *   we don't use that feature.  It's better to cache.
87 	 */
88 
89 	switch (reg) {
90 	case RK817_SECONDS_REG ... RK817_WEEKS_REG:
91 	case RK817_RTC_STATUS_REG:
92 	case RK817_CODEC_DTOP_LPT_SRST:
93 	case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
94 	case RK817_PMIC_CHRG_STS:
95 	case RK817_PMIC_CHRG_OUT:
96 	case RK817_PMIC_CHRG_IN:
97 	case RK817_INT_STS_REG0:
98 	case RK817_INT_STS_REG1:
99 	case RK817_INT_STS_REG2:
100 	case RK817_SYS_STS:
101 		return true;
102 	}
103 
104 	return false;
105 }
106 
107 
108 static const struct regmap_config rk818_regmap_config = {
109 	.reg_bits = 8,
110 	.val_bits = 8,
111 	.max_register = RK818_USB_CTRL_REG,
112 	.cache_type = REGCACHE_MAPLE,
113 	.volatile_reg = rk808_is_volatile_reg,
114 };
115 
116 static const struct regmap_config rk805_regmap_config = {
117 	.reg_bits = 8,
118 	.val_bits = 8,
119 	.max_register = RK805_OFF_SOURCE_REG,
120 	.cache_type = REGCACHE_MAPLE,
121 	.volatile_reg = rk808_is_volatile_reg,
122 };
123 
124 static const struct regmap_config rk808_regmap_config = {
125 	.reg_bits = 8,
126 	.val_bits = 8,
127 	.max_register = RK808_IO_POL_REG,
128 	.cache_type = REGCACHE_MAPLE,
129 	.volatile_reg = rk808_is_volatile_reg,
130 };
131 
132 static const struct regmap_config rk816_regmap_config = {
133 	.reg_bits = 8,
134 	.val_bits = 8,
135 	.max_register = RK816_DATA_REG(18),
136 	.cache_type = REGCACHE_MAPLE,
137 	.volatile_reg = rk816_is_volatile_reg,
138 };
139 
140 static const struct regmap_config rk817_regmap_config = {
141 	.reg_bits = 8,
142 	.val_bits = 8,
143 	.max_register = RK817_GPIO_INT_CFG,
144 	.cache_type = REGCACHE_NONE,
145 	.volatile_reg = rk817_is_volatile_reg,
146 };
147 
148 static const struct rk8xx_i2c_platform_data rk805_data = {
149 	.regmap_cfg = &rk805_regmap_config,
150 	.variant = RK805_ID,
151 };
152 
153 static const struct rk8xx_i2c_platform_data rk808_data = {
154 	.regmap_cfg = &rk808_regmap_config,
155 	.variant = RK808_ID,
156 };
157 
158 static const struct rk8xx_i2c_platform_data rk809_data = {
159 	.regmap_cfg = &rk817_regmap_config,
160 	.variant = RK809_ID,
161 };
162 
163 static const struct rk8xx_i2c_platform_data rk816_data = {
164 	.regmap_cfg = &rk816_regmap_config,
165 	.variant = RK816_ID,
166 };
167 
168 static const struct rk8xx_i2c_platform_data rk817_data = {
169 	.regmap_cfg = &rk817_regmap_config,
170 	.variant = RK817_ID,
171 };
172 
173 static const struct rk8xx_i2c_platform_data rk818_data = {
174 	.regmap_cfg = &rk818_regmap_config,
175 	.variant = RK818_ID,
176 };
177 
178 static int rk8xx_i2c_probe(struct i2c_client *client)
179 {
180 	const struct rk8xx_i2c_platform_data *data;
181 	struct regmap *regmap;
182 
183 	data = device_get_match_data(&client->dev);
184 	if (!data)
185 		return -ENODEV;
186 
187 	regmap = devm_regmap_init_i2c(client, data->regmap_cfg);
188 	if (IS_ERR(regmap))
189 		return dev_err_probe(&client->dev, PTR_ERR(regmap),
190 				     "regmap initialization failed\n");
191 
192 	return rk8xx_probe(&client->dev, data->variant, client->irq, regmap);
193 }
194 
195 static void rk8xx_i2c_shutdown(struct i2c_client *client)
196 {
197 	rk8xx_shutdown(&client->dev);
198 }
199 
200 static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
201 
202 static const struct of_device_id rk8xx_i2c_of_match[] = {
203 	{ .compatible = "rockchip,rk805", .data = &rk805_data },
204 	{ .compatible = "rockchip,rk808", .data = &rk808_data },
205 	{ .compatible = "rockchip,rk809", .data = &rk809_data },
206 	{ .compatible = "rockchip,rk816", .data = &rk816_data },
207 	{ .compatible = "rockchip,rk817", .data = &rk817_data },
208 	{ .compatible = "rockchip,rk818", .data = &rk818_data },
209 	{ },
210 };
211 MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
212 
213 static struct i2c_driver rk8xx_i2c_driver = {
214 	.driver = {
215 		.name = "rk8xx-i2c",
216 		.of_match_table = rk8xx_i2c_of_match,
217 		.pm = &rk8xx_i2c_pm_ops,
218 	},
219 	.probe = rk8xx_i2c_probe,
220 	.shutdown  = rk8xx_i2c_shutdown,
221 };
222 module_i2c_driver(rk8xx_i2c_driver);
223 
224 MODULE_LICENSE("GPL");
225 MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
226 MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
227 MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
228 MODULE_DESCRIPTION("RK8xx I2C PMIC driver");
229