xref: /linux/drivers/mfd/sec-i2c.c (revision 26ba30221c03364d6ed9910be8da4c1fd871b07b)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2012 Samsung Electronics Co., Ltd
4  *                http://www.samsung.com
5  * Copyright 2025 Linaro Ltd.
6  *
7  * Samsung SxM I2C driver
8  */
9 
10 #include <linux/dev_printk.h>
11 #include <linux/err.h>
12 #include <linux/i2c.h>
13 #include <linux/mfd/samsung/core.h>
14 #include <linux/mfd/samsung/s2mpa01.h>
15 #include <linux/mfd/samsung/s2mps11.h>
16 #include <linux/mfd/samsung/s2mps13.h>
17 #include <linux/mfd/samsung/s2mps14.h>
18 #include <linux/mfd/samsung/s2mps15.h>
19 #include <linux/mfd/samsung/s2mpu02.h>
20 #include <linux/mfd/samsung/s2mu005.h>
21 #include <linux/mfd/samsung/s5m8767.h>
22 #include <linux/module.h>
23 #include <linux/pm.h>
24 #include <linux/property.h>
25 #include <linux/regmap.h>
26 #include "sec-core.h"
27 
28 struct sec_pmic_i2c_platform_data {
29 	const struct regmap_config *regmap_cfg;
30 	int device_type;
31 };
32 
33 static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
34 {
35 	switch (reg) {
36 	case S2MPA01_REG_INT1M:
37 	case S2MPA01_REG_INT2M:
38 	case S2MPA01_REG_INT3M:
39 		return false;
40 	default:
41 		return true;
42 	}
43 }
44 
45 static bool s2mps11_volatile(struct device *dev, unsigned int reg)
46 {
47 	switch (reg) {
48 	case S2MPS11_REG_INT1M:
49 	case S2MPS11_REG_INT2M:
50 	case S2MPS11_REG_INT3M:
51 		return false;
52 	default:
53 		return true;
54 	}
55 }
56 
57 static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
58 {
59 	switch (reg) {
60 	case S2MPU02_REG_INT1M:
61 	case S2MPU02_REG_INT2M:
62 	case S2MPU02_REG_INT3M:
63 		return false;
64 	default:
65 		return true;
66 	}
67 }
68 
69 static bool s2mu005_volatile(struct device *dev, unsigned int reg)
70 {
71 	switch (reg) {
72 	case S2MU005_REG_CHGR_INT1M:
73 	case S2MU005_REG_FLED_INT1M:
74 	case S2MU005_REG_MUIC_INT1M:
75 	case S2MU005_REG_MUIC_INT2M:
76 		return false;
77 	default:
78 		return true;
79 	}
80 }
81 
82 static const struct regmap_config s2dos05_regmap_config = {
83 	.reg_bits = 8,
84 	.val_bits = 8,
85 };
86 
87 static const struct regmap_config s2mpa01_regmap_config = {
88 	.reg_bits = 8,
89 	.val_bits = 8,
90 
91 	.max_register = S2MPA01_REG_LDO_OVCB4,
92 	.volatile_reg = s2mpa01_volatile,
93 	.cache_type = REGCACHE_FLAT,
94 };
95 
96 static const struct regmap_config s2mps11_regmap_config = {
97 	.reg_bits = 8,
98 	.val_bits = 8,
99 
100 	.max_register = S2MPS11_REG_L38CTRL,
101 	.volatile_reg = s2mps11_volatile,
102 	.cache_type = REGCACHE_FLAT,
103 };
104 
105 static const struct regmap_config s2mps13_regmap_config = {
106 	.reg_bits = 8,
107 	.val_bits = 8,
108 
109 	.max_register = S2MPS13_REG_LDODSCH5,
110 	.volatile_reg = s2mps11_volatile,
111 	.cache_type = REGCACHE_FLAT,
112 };
113 
114 static const struct regmap_config s2mps14_regmap_config = {
115 	.reg_bits = 8,
116 	.val_bits = 8,
117 
118 	.max_register = S2MPS14_REG_LDODSCH3,
119 	.volatile_reg = s2mps11_volatile,
120 	.cache_type = REGCACHE_FLAT,
121 };
122 
123 static const struct regmap_config s2mps15_regmap_config = {
124 	.reg_bits = 8,
125 	.val_bits = 8,
126 
127 	.max_register = S2MPS15_REG_LDODSCH4,
128 	.volatile_reg = s2mps11_volatile,
129 	.cache_type = REGCACHE_FLAT,
130 };
131 
132 static const struct regmap_config s2mpu02_regmap_config = {
133 	.reg_bits = 8,
134 	.val_bits = 8,
135 
136 	.max_register = S2MPU02_REG_DVSDATA,
137 	.volatile_reg = s2mpu02_volatile,
138 	.cache_type = REGCACHE_FLAT,
139 };
140 
141 static const struct regmap_config s2mpu05_regmap_config = {
142 	.reg_bits = 8,
143 	.val_bits = 8,
144 };
145 
146 static const struct regmap_config s2mu005_regmap_config = {
147 	.reg_bits = 8,
148 	.val_bits = 8,
149 
150 	.max_register = S2MU005_REG_MUIC_LDOADC_H,
151 	.volatile_reg = s2mu005_volatile,
152 	.cache_type = REGCACHE_FLAT_S,
153 };
154 
155 static const struct regmap_config s5m8767_regmap_config = {
156 	.reg_bits = 8,
157 	.val_bits = 8,
158 
159 	.max_register = S5M8767_REG_LDO28CTRL,
160 	.volatile_reg = s2mps11_volatile,
161 	.cache_type = REGCACHE_FLAT,
162 };
163 
164 static int sec_pmic_i2c_probe(struct i2c_client *client)
165 {
166 	const struct sec_pmic_i2c_platform_data *pdata;
167 	struct regmap *regmap_pmic;
168 
169 	pdata = device_get_match_data(&client->dev);
170 	if (!pdata)
171 		return dev_err_probe(&client->dev, -ENODEV,
172 				     "Unsupported device type\n");
173 
174 	regmap_pmic = devm_regmap_init_i2c(client, pdata->regmap_cfg);
175 	if (IS_ERR(regmap_pmic))
176 		return dev_err_probe(&client->dev, PTR_ERR(regmap_pmic),
177 				     "regmap init failed\n");
178 
179 	return sec_pmic_probe(&client->dev, pdata->device_type, client->irq,
180 			      regmap_pmic, client);
181 }
182 
183 static void sec_pmic_i2c_shutdown(struct i2c_client *i2c)
184 {
185 	sec_pmic_shutdown(&i2c->dev);
186 }
187 
188 static const struct sec_pmic_i2c_platform_data s2dos05_data = {
189 	.regmap_cfg = &s2dos05_regmap_config,
190 	.device_type = S2DOS05
191 };
192 
193 static const struct sec_pmic_i2c_platform_data s2mpa01_data = {
194 	.regmap_cfg = &s2mpa01_regmap_config,
195 	.device_type = S2MPA01,
196 };
197 
198 static const struct sec_pmic_i2c_platform_data s2mps11_data = {
199 	.regmap_cfg = &s2mps11_regmap_config,
200 	.device_type = S2MPS11X,
201 };
202 
203 static const struct sec_pmic_i2c_platform_data s2mps13_data = {
204 	.regmap_cfg = &s2mps13_regmap_config,
205 	.device_type = S2MPS13X,
206 };
207 
208 static const struct sec_pmic_i2c_platform_data s2mps14_data = {
209 	.regmap_cfg = &s2mps14_regmap_config,
210 	.device_type = S2MPS14X,
211 };
212 
213 static const struct sec_pmic_i2c_platform_data s2mps15_data = {
214 	.regmap_cfg = &s2mps15_regmap_config,
215 	.device_type = S2MPS15X,
216 };
217 
218 static const struct sec_pmic_i2c_platform_data s2mpu02_data = {
219 	.regmap_cfg = &s2mpu02_regmap_config,
220 	.device_type = S2MPU02,
221 };
222 
223 static const struct sec_pmic_i2c_platform_data s2mpu05_data = {
224 	.regmap_cfg = &s2mpu05_regmap_config,
225 	.device_type = S2MPU05,
226 };
227 
228 static const struct sec_pmic_i2c_platform_data s2mu005_data = {
229 	.regmap_cfg = &s2mu005_regmap_config,
230 	.device_type = S2MU005,
231 };
232 
233 static const struct sec_pmic_i2c_platform_data s5m8767_data = {
234 	.regmap_cfg = &s5m8767_regmap_config,
235 	.device_type = S5M8767X,
236 };
237 
238 static const struct of_device_id sec_pmic_i2c_of_match[] = {
239 	{ .compatible = "samsung,s2dos05", .data = &s2dos05_data, },
240 	{ .compatible = "samsung,s2mpa01-pmic", .data = &s2mpa01_data, },
241 	{ .compatible = "samsung,s2mps11-pmic", .data = &s2mps11_data, },
242 	{ .compatible = "samsung,s2mps13-pmic", .data = &s2mps13_data, },
243 	{ .compatible = "samsung,s2mps14-pmic", .data = &s2mps14_data, },
244 	{ .compatible = "samsung,s2mps15-pmic", .data = &s2mps15_data, },
245 	{ .compatible = "samsung,s2mpu02-pmic", .data = &s2mpu02_data, },
246 	{ .compatible = "samsung,s2mpu05-pmic", .data = &s2mpu05_data, },
247 	{ .compatible = "samsung,s2mu005-pmic", .data = &s2mu005_data, },
248 	{ .compatible = "samsung,s5m8767-pmic", .data = &s5m8767_data, },
249 	{ },
250 };
251 MODULE_DEVICE_TABLE(of, sec_pmic_i2c_of_match);
252 
253 static struct i2c_driver sec_pmic_i2c_driver = {
254 	.driver = {
255 		.name = "sec-pmic-i2c",
256 		.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
257 		.of_match_table = sec_pmic_i2c_of_match,
258 	},
259 	.probe = sec_pmic_i2c_probe,
260 	.shutdown = sec_pmic_i2c_shutdown,
261 };
262 module_i2c_driver(sec_pmic_i2c_driver);
263 
264 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
265 MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");
266 MODULE_DESCRIPTION("I2C driver for the Samsung S5M");
267 MODULE_LICENSE("GPL");
268