projects/linux·blob master · refs

267 lines · 6.6 KiB

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
28struct sec_pmic_i2c_platform_data {
29 const struct regmap_config *regmap_cfg;
30 int device_type;
31};
32
33static 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
45static 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
57static 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
69static 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
82static const struct regmap_config s2dos05_regmap_config = {
83 .reg_bits = 8,
84 .val_bits = 8,
85};
86
87static 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
96static 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
105static 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
114static 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
123static 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
132static 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
141static const struct regmap_config s2mpu05_regmap_config = {
142 .reg_bits = 8,
143 .val_bits = 8,
144};
145
146static 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
155static 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
164static 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
183static void sec_pmic_i2c_shutdown(struct i2c_client *i2c)
184{
185 sec_pmic_shutdown(&i2c->dev);
186}
187
188static const struct sec_pmic_i2c_platform_data s2dos05_data = {
189 .regmap_cfg = &s2dos05_regmap_config,
190 .device_type = S2DOS05
191};
192
193static const struct sec_pmic_i2c_platform_data s2mpa01_data = {
194 .regmap_cfg = &s2mpa01_regmap_config,
195 .device_type = S2MPA01,
196};
197
198static const struct sec_pmic_i2c_platform_data s2mps11_data = {
199 .regmap_cfg = &s2mps11_regmap_config,
200 .device_type = S2MPS11X,
201};
202
203static const struct sec_pmic_i2c_platform_data s2mps13_data = {
204 .regmap_cfg = &s2mps13_regmap_config,
205 .device_type = S2MPS13X,
206};
207
208static const struct sec_pmic_i2c_platform_data s2mps14_data = {
209 .regmap_cfg = &s2mps14_regmap_config,
210 .device_type = S2MPS14X,
211};
212
213static const struct sec_pmic_i2c_platform_data s2mps15_data = {
214 .regmap_cfg = &s2mps15_regmap_config,
215 .device_type = S2MPS15X,
216};
217
218static const struct sec_pmic_i2c_platform_data s2mpu02_data = {
219 .regmap_cfg = &s2mpu02_regmap_config,
220 .device_type = S2MPU02,
221};
222
223static const struct sec_pmic_i2c_platform_data s2mpu05_data = {
224 .regmap_cfg = &s2mpu05_regmap_config,
225 .device_type = S2MPU05,
226};
227
228static const struct sec_pmic_i2c_platform_data s2mu005_data = {
229 .regmap_cfg = &s2mu005_regmap_config,
230 .device_type = S2MU005,
231};
232
233static const struct sec_pmic_i2c_platform_data s5m8767_data = {
234 .regmap_cfg = &s5m8767_regmap_config,
235 .device_type = S5M8767X,
236};
237
238static 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};
251MODULE_DEVICE_TABLE(of, sec_pmic_i2c_of_match);
252
253static 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};
262module_i2c_driver(sec_pmic_i2c_driver);
263
264MODULE_AUTHOR("Sangbeom Kim <[email protected]>");
265MODULE_AUTHOR("André Draszik <[email protected]>");
266MODULE_DESCRIPTION("I2C driver for the Samsung S5M");
267MODULE_LICENSE("GPL");