1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/i2c.h>
3 #include <linux/module.h>
4 #include <linux/platform_device.h>
5 #include <linux/regmap.h>
6 #include <linux/regulator/driver.h>
7 
8 #include <linux/mfd/88pm886.h>
9 
10 static const struct regmap_config pm886_regulator_regmap_config = {
11 	.reg_bits = 8,
12 	.val_bits = 8,
13 	.max_register = PM886_REG_BUCK5_VOUT,
14 };
15 
16 static const struct regulator_ops pm886_ldo_ops = {
17 	.list_voltage = regulator_list_voltage_table,
18 	.map_voltage = regulator_map_voltage_iterate,
19 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
20 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
21 	.enable = regulator_enable_regmap,
22 	.disable = regulator_disable_regmap,
23 	.is_enabled = regulator_is_enabled_regmap,
24 };
25 
26 static const struct regulator_ops pm886_buck_ops = {
27 	.list_voltage = regulator_list_voltage_linear_range,
28 	.map_voltage = regulator_map_voltage_linear_range,
29 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
30 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
31 	.enable = regulator_enable_regmap,
32 	.disable = regulator_disable_regmap,
33 	.is_enabled = regulator_is_enabled_regmap,
34 };
35 
36 static const unsigned int pm886_ldo_volt_table1[] = {
37 	1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000,
38 };
39 
40 static const unsigned int pm886_ldo_volt_table2[] = {
41 	1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000,
42 	2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
43 };
44 
45 static const unsigned int pm886_ldo_volt_table3[] = {
46 	1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000,
47 };
48 
49 static const struct linear_range pm886_buck_volt_ranges1[] = {
50 	REGULATOR_LINEAR_RANGE(600000, 0, 79, 12500),
51 	REGULATOR_LINEAR_RANGE(1600000, 80, 84, 50000),
52 };
53 
54 static const struct linear_range pm886_buck_volt_ranges2[] = {
55 	REGULATOR_LINEAR_RANGE(600000, 0, 79, 12500),
56 	REGULATOR_LINEAR_RANGE(1600000, 80, 114, 50000),
57 };
58 
59 static struct regulator_desc pm886_regulators[] = {
60 	{
61 		.name = "LDO1",
62 		.regulators_node = "regulators",
63 		.of_match = "ldo1",
64 		.ops = &pm886_ldo_ops,
65 		.type = REGULATOR_VOLTAGE,
66 		.enable_reg = PM886_REG_LDO_EN1,
67 		.enable_mask = BIT(0),
68 		.volt_table = pm886_ldo_volt_table1,
69 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),
70 		.vsel_reg = PM886_REG_LDO1_VOUT,
71 		.vsel_mask = PM886_LDO_VSEL_MASK,
72 	},
73 	{
74 		.name = "LDO2",
75 		.regulators_node = "regulators",
76 		.of_match = "ldo2",
77 		.ops = &pm886_ldo_ops,
78 		.type = REGULATOR_VOLTAGE,
79 		.enable_reg = PM886_REG_LDO_EN1,
80 		.enable_mask = BIT(1),
81 		.volt_table = pm886_ldo_volt_table1,
82 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),
83 		.vsel_reg = PM886_REG_LDO2_VOUT,
84 		.vsel_mask = PM886_LDO_VSEL_MASK,
85 	},
86 	{
87 		.name = "LDO3",
88 		.regulators_node = "regulators",
89 		.of_match = "ldo3",
90 		.ops = &pm886_ldo_ops,
91 		.type = REGULATOR_VOLTAGE,
92 		.enable_reg = PM886_REG_LDO_EN1,
93 		.enable_mask = BIT(2),
94 		.volt_table = pm886_ldo_volt_table1,
95 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),
96 		.vsel_reg = PM886_REG_LDO3_VOUT,
97 		.vsel_mask = PM886_LDO_VSEL_MASK,
98 	},
99 	{
100 		.name = "LDO4",
101 		.regulators_node = "regulators",
102 		.of_match = "ldo4",
103 		.ops = &pm886_ldo_ops,
104 		.type = REGULATOR_VOLTAGE,
105 		.enable_reg = PM886_REG_LDO_EN1,
106 		.enable_mask = BIT(3),
107 		.volt_table = pm886_ldo_volt_table2,
108 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
109 		.vsel_reg = PM886_REG_LDO4_VOUT,
110 		.vsel_mask = PM886_LDO_VSEL_MASK,
111 	},
112 	{
113 		.name = "LDO5",
114 		.regulators_node = "regulators",
115 		.of_match = "ldo5",
116 		.ops = &pm886_ldo_ops,
117 		.type = REGULATOR_VOLTAGE,
118 		.enable_reg = PM886_REG_LDO_EN1,
119 		.enable_mask = BIT(4),
120 		.volt_table = pm886_ldo_volt_table2,
121 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
122 		.vsel_reg = PM886_REG_LDO5_VOUT,
123 		.vsel_mask = PM886_LDO_VSEL_MASK,
124 	},
125 	{
126 		.name = "LDO6",
127 		.regulators_node = "regulators",
128 		.of_match = "ldo6",
129 		.ops = &pm886_ldo_ops,
130 		.type = REGULATOR_VOLTAGE,
131 		.enable_reg = PM886_REG_LDO_EN1,
132 		.enable_mask = BIT(5),
133 		.volt_table = pm886_ldo_volt_table2,
134 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
135 		.vsel_reg = PM886_REG_LDO6_VOUT,
136 		.vsel_mask = PM886_LDO_VSEL_MASK,
137 	},
138 	{
139 		.name = "LDO7",
140 		.regulators_node = "regulators",
141 		.of_match = "ldo7",
142 		.ops = &pm886_ldo_ops,
143 		.type = REGULATOR_VOLTAGE,
144 		.enable_reg = PM886_REG_LDO_EN1,
145 		.enable_mask = BIT(6),
146 		.volt_table = pm886_ldo_volt_table2,
147 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
148 		.vsel_reg = PM886_REG_LDO7_VOUT,
149 		.vsel_mask = PM886_LDO_VSEL_MASK,
150 	},
151 	{
152 		.name = "LDO8",
153 		.regulators_node = "regulators",
154 		.of_match = "ldo8",
155 		.ops = &pm886_ldo_ops,
156 		.type = REGULATOR_VOLTAGE,
157 		.enable_reg = PM886_REG_LDO_EN1,
158 		.enable_mask = BIT(7),
159 		.volt_table = pm886_ldo_volt_table2,
160 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
161 		.vsel_reg = PM886_REG_LDO8_VOUT,
162 		.vsel_mask = PM886_LDO_VSEL_MASK,
163 	},
164 	{
165 		.name = "LDO9",
166 		.regulators_node = "regulators",
167 		.of_match = "ldo9",
168 		.ops = &pm886_ldo_ops,
169 		.type = REGULATOR_VOLTAGE,
170 		.enable_reg = PM886_REG_LDO_EN2,
171 		.enable_mask = BIT(0),
172 		.volt_table = pm886_ldo_volt_table2,
173 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
174 		.vsel_reg = PM886_REG_LDO9_VOUT,
175 		.vsel_mask = PM886_LDO_VSEL_MASK,
176 	},
177 	{
178 		.name = "LDO10",
179 		.regulators_node = "regulators",
180 		.of_match = "ldo10",
181 		.ops = &pm886_ldo_ops,
182 		.type = REGULATOR_VOLTAGE,
183 		.enable_reg = PM886_REG_LDO_EN2,
184 		.enable_mask = BIT(1),
185 		.volt_table = pm886_ldo_volt_table2,
186 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
187 		.vsel_reg = PM886_REG_LDO10_VOUT,
188 		.vsel_mask = PM886_LDO_VSEL_MASK,
189 	},
190 	{
191 		.name = "LDO11",
192 		.regulators_node = "regulators",
193 		.of_match = "ldo11",
194 		.ops = &pm886_ldo_ops,
195 		.type = REGULATOR_VOLTAGE,
196 		.enable_reg = PM886_REG_LDO_EN2,
197 		.enable_mask = BIT(2),
198 		.volt_table = pm886_ldo_volt_table2,
199 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
200 		.vsel_reg = PM886_REG_LDO11_VOUT,
201 		.vsel_mask = PM886_LDO_VSEL_MASK,
202 	},
203 	{
204 		.name = "LDO12",
205 		.regulators_node = "regulators",
206 		.of_match = "ldo12",
207 		.ops = &pm886_ldo_ops,
208 		.type = REGULATOR_VOLTAGE,
209 		.enable_reg = PM886_REG_LDO_EN2,
210 		.enable_mask = BIT(3),
211 		.volt_table = pm886_ldo_volt_table2,
212 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
213 		.vsel_reg = PM886_REG_LDO12_VOUT,
214 		.vsel_mask = PM886_LDO_VSEL_MASK,
215 	},
216 	{
217 		.name = "LDO13",
218 		.regulators_node = "regulators",
219 		.of_match = "ldo13",
220 		.ops = &pm886_ldo_ops,
221 		.type = REGULATOR_VOLTAGE,
222 		.enable_reg = PM886_REG_LDO_EN2,
223 		.enable_mask = BIT(4),
224 		.volt_table = pm886_ldo_volt_table2,
225 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
226 		.vsel_reg = PM886_REG_LDO13_VOUT,
227 		.vsel_mask = PM886_LDO_VSEL_MASK,
228 	},
229 	{
230 		.name = "LDO14",
231 		.regulators_node = "regulators",
232 		.of_match = "ldo14",
233 		.ops = &pm886_ldo_ops,
234 		.type = REGULATOR_VOLTAGE,
235 		.enable_reg = PM886_REG_LDO_EN2,
236 		.enable_mask = BIT(5),
237 		.volt_table = pm886_ldo_volt_table2,
238 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
239 		.vsel_reg = PM886_REG_LDO14_VOUT,
240 		.vsel_mask = PM886_LDO_VSEL_MASK,
241 	},
242 	{
243 		.name = "LDO15",
244 		.regulators_node = "regulators",
245 		.of_match = "ldo15",
246 		.ops = &pm886_ldo_ops,
247 		.type = REGULATOR_VOLTAGE,
248 		.enable_reg = PM886_REG_LDO_EN2,
249 		.enable_mask = BIT(6),
250 		.volt_table = pm886_ldo_volt_table2,
251 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
252 		.vsel_reg = PM886_REG_LDO15_VOUT,
253 		.vsel_mask = PM886_LDO_VSEL_MASK,
254 	},
255 	{
256 		.name = "LDO16",
257 		.regulators_node = "regulators",
258 		.of_match = "ldo16",
259 		.ops = &pm886_ldo_ops,
260 		.type = REGULATOR_VOLTAGE,
261 		.enable_reg = PM886_REG_LDO_EN2,
262 		.enable_mask = BIT(7),
263 		.volt_table = pm886_ldo_volt_table3,
264 		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table3),
265 		.vsel_reg = PM886_REG_LDO16_VOUT,
266 		.vsel_mask = PM886_LDO_VSEL_MASK,
267 	},
268 	{
269 		.name = "buck1",
270 		.regulators_node = "regulators",
271 		.of_match = "buck1",
272 		.ops = &pm886_buck_ops,
273 		.type = REGULATOR_VOLTAGE,
274 		.n_voltages = 85,
275 		.linear_ranges = pm886_buck_volt_ranges1,
276 		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges1),
277 		.vsel_reg = PM886_REG_BUCK1_VOUT,
278 		.vsel_mask = PM886_BUCK_VSEL_MASK,
279 		.enable_reg = PM886_REG_BUCK_EN,
280 		.enable_mask = BIT(0),
281 	},
282 	{
283 		.name = "buck2",
284 		.regulators_node = "regulators",
285 		.of_match = "buck2",
286 		.ops = &pm886_buck_ops,
287 		.type = REGULATOR_VOLTAGE,
288 		.n_voltages = 115,
289 		.linear_ranges = pm886_buck_volt_ranges2,
290 		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),
291 		.vsel_reg = PM886_REG_BUCK2_VOUT,
292 		.vsel_mask = PM886_BUCK_VSEL_MASK,
293 		.enable_reg = PM886_REG_BUCK_EN,
294 		.enable_mask = BIT(1),
295 	},
296 	{
297 		.name = "buck3",
298 		.regulators_node = "regulators",
299 		.of_match = "buck3",
300 		.ops = &pm886_buck_ops,
301 		.type = REGULATOR_VOLTAGE,
302 		.n_voltages = 115,
303 		.linear_ranges = pm886_buck_volt_ranges2,
304 		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),
305 		.vsel_reg = PM886_REG_BUCK3_VOUT,
306 		.vsel_mask = PM886_BUCK_VSEL_MASK,
307 		.enable_reg = PM886_REG_BUCK_EN,
308 		.enable_mask = BIT(2),
309 	},
310 	{
311 		.name = "buck4",
312 		.regulators_node = "regulators",
313 		.of_match = "buck4",
314 		.ops = &pm886_buck_ops,
315 		.type = REGULATOR_VOLTAGE,
316 		.n_voltages = 115,
317 		.linear_ranges = pm886_buck_volt_ranges2,
318 		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),
319 		.vsel_reg = PM886_REG_BUCK4_VOUT,
320 		.vsel_mask = PM886_BUCK_VSEL_MASK,
321 		.enable_reg = PM886_REG_BUCK_EN,
322 		.enable_mask = BIT(3),
323 	},
324 	{
325 		.name = "buck5",
326 		.regulators_node = "regulators",
327 		.of_match = "buck5",
328 		.ops = &pm886_buck_ops,
329 		.type = REGULATOR_VOLTAGE,
330 		.n_voltages = 115,
331 		.linear_ranges = pm886_buck_volt_ranges2,
332 		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),
333 		.vsel_reg = PM886_REG_BUCK5_VOUT,
334 		.vsel_mask = PM886_BUCK_VSEL_MASK,
335 		.enable_reg = PM886_REG_BUCK_EN,
336 		.enable_mask = BIT(4),
337 	},
338 };
339 
pm886_regulator_probe(struct platform_device * pdev)340 static int pm886_regulator_probe(struct platform_device *pdev)
341 {
342 	struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent);
343 	struct regulator_config rcfg = { };
344 	struct device *dev = &pdev->dev;
345 	struct regulator_desc *rdesc;
346 	struct regulator_dev *rdev;
347 	struct i2c_client *page;
348 	struct regmap *regmap;
349 
350 	page = devm_i2c_new_dummy_device(dev, chip->client->adapter,
351 			chip->client->addr + PM886_PAGE_OFFSET_REGULATORS);
352 	if (IS_ERR(page))
353 		return dev_err_probe(dev, PTR_ERR(page),
354 				"Failed to initialize regulators client\n");
355 
356 	regmap = devm_regmap_init_i2c(page, &pm886_regulator_regmap_config);
357 	if (IS_ERR(regmap))
358 		return dev_err_probe(dev, PTR_ERR(regmap),
359 				"Failed to initialize regulators regmap\n");
360 	rcfg.regmap = regmap;
361 
362 	rcfg.dev = dev->parent;
363 
364 	for (int i = 0; i < ARRAY_SIZE(pm886_regulators); i++) {
365 		rdesc = &pm886_regulators[i];
366 		rdev = devm_regulator_register(dev, rdesc, &rcfg);
367 		if (IS_ERR(rdev))
368 			return dev_err_probe(dev, PTR_ERR(rdev),
369 					"Failed to register %s\n", rdesc->name);
370 	}
371 
372 	return 0;
373 }
374 
375 static const struct platform_device_id pm886_regulator_id_table[] = {
376 	{ "88pm886-regulator", },
377 	{ }
378 };
379 MODULE_DEVICE_TABLE(platform, pm886_regulator_id_table);
380 
381 static struct platform_driver pm886_regulator_driver = {
382 	.driver = {
383 		.name = "88pm886-regulator",
384 	},
385 	.probe = pm886_regulator_probe,
386 	.id_table = pm886_regulator_id_table,
387 };
388 module_platform_driver(pm886_regulator_driver);
389 
390 MODULE_DESCRIPTION("Marvell 88PM886 PMIC regulator driver");
391 MODULE_AUTHOR("Karel Balej <balejk@matfyz.cz>");
392 MODULE_LICENSE("GPL");
393