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