Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
19struct rk8xx_i2c_platform_data {
20 const struct regmap_config *regmap_cfg;
21 int variant;
22};
23
24static 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
52static 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
81static 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
108static 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
116static 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
124static 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
132static 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
140static 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
148static const struct rk8xx_i2c_platform_data rk805_data = {
149 .regmap_cfg = &rk805_regmap_config,
150 .variant = RK805_ID,
151};
152
153static const struct rk8xx_i2c_platform_data rk808_data = {
154 .regmap_cfg = &rk808_regmap_config,
155 .variant = RK808_ID,
156};
157
158static const struct rk8xx_i2c_platform_data rk809_data = {
159 .regmap_cfg = &rk817_regmap_config,
160 .variant = RK809_ID,
161};
162
163static const struct rk8xx_i2c_platform_data rk816_data = {
164 .regmap_cfg = &rk816_regmap_config,
165 .variant = RK816_ID,
166};
167
168static const struct rk8xx_i2c_platform_data rk817_data = {
169 .regmap_cfg = &rk817_regmap_config,
170 .variant = RK817_ID,
171};
172
173static const struct rk8xx_i2c_platform_data rk818_data = {
174 .regmap_cfg = &rk818_regmap_config,
175 .variant = RK818_ID,
176};
177
178static 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
195static void rk8xx_i2c_shutdown(struct i2c_client *client)
196{
197 rk8xx_shutdown(&client->dev);
198}
199
200static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
201
202static 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};
211MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
212
213static 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};
222module_i2c_driver(rk8xx_i2c_driver);
223
224MODULE_LICENSE("GPL");
225MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
226MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
227MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
228MODULE_DESCRIPTION("RK8xx I2C PMIC driver");