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/s5m8767.h>
21#include <linux/mod_devicetable.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 const struct regmap_config s2dos05_regmap_config = {
70 .reg_bits = 8,
71 .val_bits = 8,
72};
73
74static const struct regmap_config s2mpa01_regmap_config = {
75 .reg_bits = 8,
76 .val_bits = 8,
77
78 .max_register = S2MPA01_REG_LDO_OVCB4,
79 .volatile_reg = s2mpa01_volatile,
80 .cache_type = REGCACHE_FLAT,
81};
82
83static const struct regmap_config s2mps11_regmap_config = {
84 .reg_bits = 8,
85 .val_bits = 8,
86
87 .max_register = S2MPS11_REG_L38CTRL,
88 .volatile_reg = s2mps11_volatile,
89 .cache_type = REGCACHE_FLAT,
90};
91
92static const struct regmap_config s2mps13_regmap_config = {
93 .reg_bits = 8,
94 .val_bits = 8,
95
96 .max_register = S2MPS13_REG_LDODSCH5,
97 .volatile_reg = s2mps11_volatile,
98 .cache_type = REGCACHE_FLAT,
99};
100
101static const struct regmap_config s2mps14_regmap_config = {
102 .reg_bits = 8,
103 .val_bits = 8,
104
105 .max_register = S2MPS14_REG_LDODSCH3,
106 .volatile_reg = s2mps11_volatile,
107 .cache_type = REGCACHE_FLAT,
108};
109
110static const struct regmap_config s2mps15_regmap_config = {
111 .reg_bits = 8,
112 .val_bits = 8,
113
114 .max_register = S2MPS15_REG_LDODSCH4,
115 .volatile_reg = s2mps11_volatile,
116 .cache_type = REGCACHE_FLAT,
117};
118
119static const struct regmap_config s2mpu02_regmap_config = {
120 .reg_bits = 8,
121 .val_bits = 8,
122
123 .max_register = S2MPU02_REG_DVSDATA,
124 .volatile_reg = s2mpu02_volatile,
125 .cache_type = REGCACHE_FLAT,
126};
127
128static const struct regmap_config s2mpu05_regmap_config = {
129 .reg_bits = 8,
130 .val_bits = 8,
131};
132
133static const struct regmap_config s5m8767_regmap_config = {
134 .reg_bits = 8,
135 .val_bits = 8,
136
137 .max_register = S5M8767_REG_LDO28CTRL,
138 .volatile_reg = s2mps11_volatile,
139 .cache_type = REGCACHE_FLAT,
140};
141
142static int sec_pmic_i2c_probe(struct i2c_client *client)
143{
144 const struct sec_pmic_i2c_platform_data *pdata;
145 struct regmap *regmap_pmic;
146
147 pdata = device_get_match_data(dev: &client->dev);
148 if (!pdata)
149 return dev_err_probe(dev: &client->dev, err: -ENODEV,
150 fmt: "Unsupported device type\n");
151
152 regmap_pmic = devm_regmap_init_i2c(client, pdata->regmap_cfg);
153 if (IS_ERR(ptr: regmap_pmic))
154 return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: regmap_pmic),
155 fmt: "regmap init failed\n");
156
157 return sec_pmic_probe(dev: &client->dev, device_type: pdata->device_type, irq: client->irq,
158 regmap: regmap_pmic, client);
159}
160
161static void sec_pmic_i2c_shutdown(struct i2c_client *i2c)
162{
163 sec_pmic_shutdown(dev: &i2c->dev);
164}
165
166static const struct sec_pmic_i2c_platform_data s2dos05_data = {
167 .regmap_cfg = &s2dos05_regmap_config,
168 .device_type = S2DOS05
169};
170
171static const struct sec_pmic_i2c_platform_data s2mpa01_data = {
172 .regmap_cfg = &s2mpa01_regmap_config,
173 .device_type = S2MPA01,
174};
175
176static const struct sec_pmic_i2c_platform_data s2mps11_data = {
177 .regmap_cfg = &s2mps11_regmap_config,
178 .device_type = S2MPS11X,
179};
180
181static const struct sec_pmic_i2c_platform_data s2mps13_data = {
182 .regmap_cfg = &s2mps13_regmap_config,
183 .device_type = S2MPS13X,
184};
185
186static const struct sec_pmic_i2c_platform_data s2mps14_data = {
187 .regmap_cfg = &s2mps14_regmap_config,
188 .device_type = S2MPS14X,
189};
190
191static const struct sec_pmic_i2c_platform_data s2mps15_data = {
192 .regmap_cfg = &s2mps15_regmap_config,
193 .device_type = S2MPS15X,
194};
195
196static const struct sec_pmic_i2c_platform_data s2mpu02_data = {
197 .regmap_cfg = &s2mpu02_regmap_config,
198 .device_type = S2MPU02,
199};
200
201static const struct sec_pmic_i2c_platform_data s2mpu05_data = {
202 .regmap_cfg = &s2mpu05_regmap_config,
203 .device_type = S2MPU05,
204};
205
206static const struct sec_pmic_i2c_platform_data s5m8767_data = {
207 .regmap_cfg = &s5m8767_regmap_config,
208 .device_type = S5M8767X,
209};
210
211static const struct of_device_id sec_pmic_i2c_of_match[] = {
212 { .compatible = "samsung,s2dos05", .data = &s2dos05_data, },
213 { .compatible = "samsung,s2mpa01-pmic", .data = &s2mpa01_data, },
214 { .compatible = "samsung,s2mps11-pmic", .data = &s2mps11_data, },
215 { .compatible = "samsung,s2mps13-pmic", .data = &s2mps13_data, },
216 { .compatible = "samsung,s2mps14-pmic", .data = &s2mps14_data, },
217 { .compatible = "samsung,s2mps15-pmic", .data = &s2mps15_data, },
218 { .compatible = "samsung,s2mpu02-pmic", .data = &s2mpu02_data, },
219 { .compatible = "samsung,s2mpu05-pmic", .data = &s2mpu05_data, },
220 { .compatible = "samsung,s5m8767-pmic", .data = &s5m8767_data, },
221 { },
222};
223MODULE_DEVICE_TABLE(of, sec_pmic_i2c_of_match);
224
225static struct i2c_driver sec_pmic_i2c_driver = {
226 .driver = {
227 .name = "sec-pmic-i2c",
228 .pm = pm_sleep_ptr(&sec_pmic_pm_ops),
229 .of_match_table = sec_pmic_i2c_of_match,
230 },
231 .probe = sec_pmic_i2c_probe,
232 .shutdown = sec_pmic_i2c_shutdown,
233};
234module_i2c_driver(sec_pmic_i2c_driver);
235
236MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
237MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");
238MODULE_DESCRIPTION("I2C driver for the Samsung S5M");
239MODULE_LICENSE("GPL");
240

source code of linux/drivers/mfd/sec-i2c.c