]>
Commit | Line | Data |
---|---|---|
c20e8c5b SR |
1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* | |
3 | * Rockchip RK808/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 <[email protected]> | |
9 | * Author: Zhang Qing <[email protected]> | |
10 | * Author: Wadim Egorov <[email protected]> | |
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 | ||
74413bd6 SR |
19 | struct rk8xx_i2c_platform_data { |
20 | const struct regmap_config *regmap_cfg; | |
21 | int variant; | |
22 | }; | |
23 | ||
c20e8c5b SR |
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 rk817_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 | */ | |
59 | ||
60 | switch (reg) { | |
61 | case RK817_SECONDS_REG ... RK817_WEEKS_REG: | |
62 | case RK817_RTC_STATUS_REG: | |
63 | case RK817_CODEC_DTOP_LPT_SRST: | |
64 | case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0: | |
65 | case RK817_PMIC_CHRG_STS: | |
66 | case RK817_PMIC_CHRG_OUT: | |
67 | case RK817_PMIC_CHRG_IN: | |
68 | case RK817_INT_STS_REG0: | |
69 | case RK817_INT_STS_REG1: | |
70 | case RK817_INT_STS_REG2: | |
71 | case RK817_SYS_STS: | |
72 | return true; | |
73 | } | |
74 | ||
75 | return false; | |
76 | } | |
77 | ||
78 | ||
79 | static const struct regmap_config rk818_regmap_config = { | |
80 | .reg_bits = 8, | |
81 | .val_bits = 8, | |
82 | .max_register = RK818_USB_CTRL_REG, | |
83 | .cache_type = REGCACHE_RBTREE, | |
84 | .volatile_reg = rk808_is_volatile_reg, | |
85 | }; | |
86 | ||
87 | static const struct regmap_config rk805_regmap_config = { | |
88 | .reg_bits = 8, | |
89 | .val_bits = 8, | |
90 | .max_register = RK805_OFF_SOURCE_REG, | |
91 | .cache_type = REGCACHE_RBTREE, | |
92 | .volatile_reg = rk808_is_volatile_reg, | |
93 | }; | |
94 | ||
95 | static const struct regmap_config rk808_regmap_config = { | |
96 | .reg_bits = 8, | |
97 | .val_bits = 8, | |
98 | .max_register = RK808_IO_POL_REG, | |
99 | .cache_type = REGCACHE_RBTREE, | |
100 | .volatile_reg = rk808_is_volatile_reg, | |
101 | }; | |
102 | ||
103 | static const struct regmap_config rk817_regmap_config = { | |
104 | .reg_bits = 8, | |
105 | .val_bits = 8, | |
106 | .max_register = RK817_GPIO_INT_CFG, | |
107 | .cache_type = REGCACHE_NONE, | |
108 | .volatile_reg = rk817_is_volatile_reg, | |
109 | }; | |
110 | ||
74413bd6 SR |
111 | static const struct rk8xx_i2c_platform_data rk805_data = { |
112 | .regmap_cfg = &rk805_regmap_config, | |
113 | .variant = RK805_ID, | |
114 | }; | |
115 | ||
116 | static const struct rk8xx_i2c_platform_data rk808_data = { | |
117 | .regmap_cfg = &rk808_regmap_config, | |
118 | .variant = RK808_ID, | |
119 | }; | |
c20e8c5b | 120 | |
74413bd6 SR |
121 | static const struct rk8xx_i2c_platform_data rk809_data = { |
122 | .regmap_cfg = &rk817_regmap_config, | |
123 | .variant = RK809_ID, | |
124 | }; | |
c20e8c5b | 125 | |
74413bd6 SR |
126 | static const struct rk8xx_i2c_platform_data rk817_data = { |
127 | .regmap_cfg = &rk817_regmap_config, | |
128 | .variant = RK817_ID, | |
129 | }; | |
c20e8c5b | 130 | |
74413bd6 SR |
131 | static const struct rk8xx_i2c_platform_data rk818_data = { |
132 | .regmap_cfg = &rk818_regmap_config, | |
133 | .variant = RK818_ID, | |
134 | }; | |
c20e8c5b SR |
135 | |
136 | static int rk8xx_i2c_probe(struct i2c_client *client) | |
137 | { | |
74413bd6 | 138 | const struct rk8xx_i2c_platform_data *data; |
c20e8c5b | 139 | struct regmap *regmap; |
c20e8c5b | 140 | |
74413bd6 SR |
141 | data = device_get_match_data(&client->dev); |
142 | if (!data) | |
143 | return -ENODEV; | |
c20e8c5b | 144 | |
74413bd6 | 145 | regmap = devm_regmap_init_i2c(client, data->regmap_cfg); |
c20e8c5b SR |
146 | if (IS_ERR(regmap)) |
147 | return dev_err_probe(&client->dev, PTR_ERR(regmap), | |
148 | "regmap initialization failed\n"); | |
149 | ||
74413bd6 | 150 | return rk8xx_probe(&client->dev, data->variant, client->irq, regmap); |
c20e8c5b SR |
151 | } |
152 | ||
153 | static void rk8xx_i2c_shutdown(struct i2c_client *client) | |
154 | { | |
155 | rk8xx_shutdown(&client->dev); | |
156 | } | |
157 | ||
158 | static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume); | |
159 | ||
160 | static const struct of_device_id rk8xx_i2c_of_match[] = { | |
74413bd6 SR |
161 | { .compatible = "rockchip,rk805", .data = &rk805_data }, |
162 | { .compatible = "rockchip,rk808", .data = &rk808_data }, | |
163 | { .compatible = "rockchip,rk809", .data = &rk809_data }, | |
164 | { .compatible = "rockchip,rk817", .data = &rk817_data }, | |
165 | { .compatible = "rockchip,rk818", .data = &rk818_data }, | |
c20e8c5b SR |
166 | { }, |
167 | }; | |
168 | MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match); | |
169 | ||
170 | static struct i2c_driver rk8xx_i2c_driver = { | |
171 | .driver = { | |
172 | .name = "rk8xx-i2c", | |
173 | .of_match_table = rk8xx_i2c_of_match, | |
174 | .pm = &rk8xx_i2c_pm_ops, | |
175 | }, | |
9816d859 | 176 | .probe = rk8xx_i2c_probe, |
c20e8c5b SR |
177 | .shutdown = rk8xx_i2c_shutdown, |
178 | }; | |
179 | module_i2c_driver(rk8xx_i2c_driver); | |
180 | ||
181 | MODULE_LICENSE("GPL"); | |
182 | MODULE_AUTHOR("Chris Zhong <[email protected]>"); | |
183 | MODULE_AUTHOR("Zhang Qing <[email protected]>"); | |
184 | MODULE_AUTHOR("Wadim Egorov <[email protected]>"); | |
185 | MODULE_DESCRIPTION("RK8xx I2C PMIC driver"); |