xref: /linux/drivers/mfd/sec-i2c.c (revision 680ef57915db0f715e99a683c15f0f9f7c700e64)
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/of.h>
24 #include <linux/pm.h>
25 #include <linux/regmap.h>
26 #include "sec-core.h"
27 
28 static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
29 {
30 	switch (reg) {
31 	case S2MPA01_REG_INT1M:
32 	case S2MPA01_REG_INT2M:
33 	case S2MPA01_REG_INT3M:
34 		return false;
35 	default:
36 		return true;
37 	}
38 }
39 
40 static bool s2mps11_volatile(struct device *dev, unsigned int reg)
41 {
42 	switch (reg) {
43 	case S2MPS11_REG_INT1M:
44 	case S2MPS11_REG_INT2M:
45 	case S2MPS11_REG_INT3M:
46 		return false;
47 	default:
48 		return true;
49 	}
50 }
51 
52 static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
53 {
54 	switch (reg) {
55 	case S2MPU02_REG_INT1M:
56 	case S2MPU02_REG_INT2M:
57 	case S2MPU02_REG_INT3M:
58 		return false;
59 	default:
60 		return true;
61 	}
62 }
63 
64 static const struct regmap_config sec_regmap_config = {
65 	.reg_bits = 8,
66 	.val_bits = 8,
67 };
68 
69 static const struct regmap_config s2mpa01_regmap_config = {
70 	.reg_bits = 8,
71 	.val_bits = 8,
72 
73 	.max_register = S2MPA01_REG_LDO_OVCB4,
74 	.volatile_reg = s2mpa01_volatile,
75 	.cache_type = REGCACHE_FLAT,
76 };
77 
78 static const struct regmap_config s2mps11_regmap_config = {
79 	.reg_bits = 8,
80 	.val_bits = 8,
81 
82 	.max_register = S2MPS11_REG_L38CTRL,
83 	.volatile_reg = s2mps11_volatile,
84 	.cache_type = REGCACHE_FLAT,
85 };
86 
87 static const struct regmap_config s2mps13_regmap_config = {
88 	.reg_bits = 8,
89 	.val_bits = 8,
90 
91 	.max_register = S2MPS13_REG_LDODSCH5,
92 	.volatile_reg = s2mps11_volatile,
93 	.cache_type = REGCACHE_FLAT,
94 };
95 
96 static const struct regmap_config s2mps14_regmap_config = {
97 	.reg_bits = 8,
98 	.val_bits = 8,
99 
100 	.max_register = S2MPS14_REG_LDODSCH3,
101 	.volatile_reg = s2mps11_volatile,
102 	.cache_type = REGCACHE_FLAT,
103 };
104 
105 static const struct regmap_config s2mps15_regmap_config = {
106 	.reg_bits = 8,
107 	.val_bits = 8,
108 
109 	.max_register = S2MPS15_REG_LDODSCH4,
110 	.volatile_reg = s2mps11_volatile,
111 	.cache_type = REGCACHE_FLAT,
112 };
113 
114 static const struct regmap_config s2mpu02_regmap_config = {
115 	.reg_bits = 8,
116 	.val_bits = 8,
117 
118 	.max_register = S2MPU02_REG_DVSDATA,
119 	.volatile_reg = s2mpu02_volatile,
120 	.cache_type = REGCACHE_FLAT,
121 };
122 
123 static const struct regmap_config s5m8767_regmap_config = {
124 	.reg_bits = 8,
125 	.val_bits = 8,
126 
127 	.max_register = S5M8767_REG_LDO28CTRL,
128 	.volatile_reg = s2mps11_volatile,
129 	.cache_type = REGCACHE_FLAT,
130 };
131 
132 static int sec_pmic_i2c_probe(struct i2c_client *client)
133 {
134 	const struct regmap_config *regmap;
135 	unsigned long device_type;
136 	struct regmap *regmap_pmic;
137 	int ret;
138 
139 	device_type = (unsigned long)of_device_get_match_data(&client->dev);
140 
141 	switch (device_type) {
142 	case S2MPA01:
143 		regmap = &s2mpa01_regmap_config;
144 		break;
145 	case S2MPS11X:
146 		regmap = &s2mps11_regmap_config;
147 		break;
148 	case S2MPS13X:
149 		regmap = &s2mps13_regmap_config;
150 		break;
151 	case S2MPS14X:
152 		regmap = &s2mps14_regmap_config;
153 		break;
154 	case S2MPS15X:
155 		regmap = &s2mps15_regmap_config;
156 		break;
157 	case S5M8767X:
158 		regmap = &s5m8767_regmap_config;
159 		break;
160 	case S2MPU02:
161 		regmap = &s2mpu02_regmap_config;
162 		break;
163 	default:
164 		regmap = &sec_regmap_config;
165 		break;
166 	}
167 
168 	regmap_pmic = devm_regmap_init_i2c(client, regmap);
169 	if (IS_ERR(regmap_pmic)) {
170 		ret = PTR_ERR(regmap_pmic);
171 		dev_err(&client->dev, "Failed to allocate register map: %d\n",
172 			ret);
173 		return ret;
174 	}
175 
176 	return sec_pmic_probe(&client->dev, device_type, client->irq,
177 			      regmap_pmic, client);
178 }
179 
180 static void sec_pmic_i2c_shutdown(struct i2c_client *i2c)
181 {
182 	sec_pmic_shutdown(&i2c->dev);
183 }
184 
185 static const struct of_device_id sec_pmic_i2c_of_match[] = {
186 	{
187 		.compatible = "samsung,s5m8767-pmic",
188 		.data = (void *)S5M8767X,
189 	}, {
190 		.compatible = "samsung,s2dos05",
191 		.data = (void *)S2DOS05,
192 	}, {
193 		.compatible = "samsung,s2mps11-pmic",
194 		.data = (void *)S2MPS11X,
195 	}, {
196 		.compatible = "samsung,s2mps13-pmic",
197 		.data = (void *)S2MPS13X,
198 	}, {
199 		.compatible = "samsung,s2mps14-pmic",
200 		.data = (void *)S2MPS14X,
201 	}, {
202 		.compatible = "samsung,s2mps15-pmic",
203 		.data = (void *)S2MPS15X,
204 	}, {
205 		.compatible = "samsung,s2mpa01-pmic",
206 		.data = (void *)S2MPA01,
207 	}, {
208 		.compatible = "samsung,s2mpu02-pmic",
209 		.data = (void *)S2MPU02,
210 	}, {
211 		.compatible = "samsung,s2mpu05-pmic",
212 		.data = (void *)S2MPU05,
213 	},
214 	{ },
215 };
216 MODULE_DEVICE_TABLE(of, sec_pmic_i2c_of_match);
217 
218 static struct i2c_driver sec_pmic_i2c_driver = {
219 	.driver = {
220 		.name = "sec-pmic-i2c",
221 		.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
222 		.of_match_table = sec_pmic_i2c_of_match,
223 	},
224 	.probe = sec_pmic_i2c_probe,
225 	.shutdown = sec_pmic_i2c_shutdown,
226 };
227 module_i2c_driver(sec_pmic_i2c_driver);
228 
229 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
230 MODULE_DESCRIPTION("I2C driver for the Samsung S5M");
231 MODULE_LICENSE("GPL");
232