Merge tag 'riscv-for-linus-6.5-rc5' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / regulator / pf8x00-regulator.c
CommitLineData
d3795d63
JT
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2017 NXP
4 * Copyright (C) 2019 Boundary Devices
5 * Copyright (C) 2020 Amarula Solutions(India)
6 */
7
8#include <linux/delay.h>
9#include <linux/err.h>
10#include <linux/gpio/consumer.h>
11#include <linux/i2c.h>
12#include <linux/module.h>
13#include <linux/regmap.h>
14#include <linux/regulator/driver.h>
15#include <linux/regulator/machine.h>
16
17/* registers */
18#define PF8X00_DEVICEID 0x00
19#define PF8X00_REVID 0x01
20#define PF8X00_EMREV 0x02
21#define PF8X00_PROGID 0x03
22#define PF8X00_IMS_INT 0x04
23#define PF8X00_IMS_THERM 0x07
24#define PF8X00_SW_MODE_INT 0x0a
25#define PF8X00_SW_MODE_MASK 0x0b
26#define PF8X00_IMS_SW_ILIM 0x12
27#define PF8X00_IMS_LDO_ILIM 0x15
28#define PF8X00_IMS_SW_UV 0x18
29#define PF8X00_IMS_SW_OV 0x1b
30#define PF8X00_IMS_LDO_UV 0x1e
31#define PF8X00_IMS_LDO_OV 0x21
32#define PF8X00_IMS_PWRON 0x24
33#define PF8X00_SYS_INT 0x27
34#define PF8X00_HARD_FAULT 0x29
35#define PF8X00_FSOB_FLAGS 0x2a
36#define PF8X00_FSOB_SELECT 0x2b
37#define PF8X00_ABIST_OV1 0x2c
38#define PF8X00_ABIST_OV2 0x2d
39#define PF8X00_ABIST_UV1 0x2e
40#define PF8X00_ABIST_UV2 0x2f
41#define PF8X00_TEST_FLAGS 0x30
42#define PF8X00_ABIST_RUN 0x31
43#define PF8X00_RANDOM_GEN 0x33
44#define PF8X00_RANDOM_CHK 0x34
45#define PF8X00_VMONEN1 0x35
46#define PF8X00_VMONEN2 0x36
47#define PF8X00_CTRL1 0x37
48#define PF8X00_CTRL2 0x38
49#define PF8X00_CTRL3 0x39
50#define PF8X00_PWRUP_CTRL 0x3a
51#define PF8X00_RESETBMCU 0x3c
52#define PF8X00_PGOOD 0x3d
53#define PF8X00_PWRDN_DLY1 0x3e
54#define PF8X00_PWRDN_DLY2 0x3f
55#define PF8X00_FREQ_CTRL 0x40
56#define PF8X00_COINCELL_CTRL 0x41
57#define PF8X00_PWRON 0x42
58#define PF8X00_WD_CONFIG 0x43
59#define PF8X00_WD_CLEAR 0x44
60#define PF8X00_WD_EXPIRE 0x45
61#define PF8X00_WD_COUNTER 0x46
62#define PF8X00_FAULT_COUNTER 0x47
63#define PF8X00_FSAFE_COUNTER 0x48
64#define PF8X00_FAULT_TIMER 0x49
65#define PF8X00_AMUX 0x4a
66#define PF8X00_SW1_CONFIG1 0x4d
67#define PF8X00_LDO1_CONFIG1 0x85
68#define PF8X00_VSNVS_CONFIG1 0x9d
69#define PF8X00_PAGE_SELECT 0x9f
70
71/* regulators */
72enum pf8x00_regulators {
73 PF8X00_LDO1,
74 PF8X00_LDO2,
75 PF8X00_LDO3,
76 PF8X00_LDO4,
77 PF8X00_BUCK1,
78 PF8X00_BUCK2,
79 PF8X00_BUCK3,
80 PF8X00_BUCK4,
81 PF8X00_BUCK5,
82 PF8X00_BUCK6,
83 PF8X00_BUCK7,
84 PF8X00_VSNVS,
85
86 PF8X00_MAX_REGULATORS,
87};
88
89enum pf8x00_buck_states {
90 SW_CONFIG1,
91 SW_CONFIG2,
92 SW_PWRUP,
93 SW_MODE1,
94 SW_RUN_VOLT,
95 SW_STBY_VOLT,
96};
97#define PF8X00_SW_BASE(i) (8 * (i - PF8X00_BUCK1) + PF8X00_SW1_CONFIG1)
98
99enum pf8x00_ldo_states {
100 LDO_CONFIG1,
101 LDO_CONFIG2,
102 LDO_PWRUP,
103 LDO_RUN_VOLT,
104 LDO_STBY_VOLT,
105};
106#define PF8X00_LDO_BASE(i) (6 * (i - PF8X00_LDO1) + PF8X00_LDO1_CONFIG1)
107
108enum swxilim_bits {
109 SWXILIM_2100_MA,
110 SWXILIM_2600_MA,
111 SWXILIM_3000_MA,
112 SWXILIM_4500_MA,
113};
114#define PF8X00_SWXILIM_SHIFT 3
115#define PF8X00_SWXILIM_MASK GENMASK(4, 3)
116#define PF8X00_SWXPHASE_MASK GENMASK(2, 0)
d3795d63
JT
117#define PF8X00_SWXPHASE_SHIFT 7
118
119enum pf8x00_devid {
120 PF8100 = 0x0,
121 PF8121A = BIT(1),
122 PF8200 = BIT(3),
123};
124#define PF8X00_FAM BIT(6)
125#define PF8X00_DEVICE_FAM_MASK GENMASK(7, 4)
126#define PF8X00_DEVICE_ID_MASK GENMASK(3, 0)
127
7fefe72b 128struct pf8x00_regulator_data {
d3795d63 129 struct regulator_desc desc;
7fefe72b
CF
130 unsigned int suspend_enable_reg;
131 unsigned int suspend_enable_mask;
132 unsigned int suspend_voltage_reg;
133 unsigned int suspend_voltage_cache;
d3795d63
JT
134};
135
136struct pf8x00_chip {
137 struct regmap *regmap;
138 struct device *dev;
139};
140
141static const struct regmap_config pf8x00_regmap_config = {
142 .reg_bits = 8,
143 .val_bits = 8,
144 .max_register = PF8X00_PAGE_SELECT,
145 .cache_type = REGCACHE_RBTREE,
146};
147
148/* VLDOx output: 1.5V to 5.0V */
149static const int pf8x00_ldo_voltages[] = {
150 1500000, 1600000, 1800000, 1850000, 2150000, 2500000, 2800000, 3000000,
151 3100000, 3150000, 3200000, 3300000, 3350000, 1650000, 1700000, 5000000,
152};
153
245f5f65
AG
154/* Output: 2.1A to 4.5A */
155static const unsigned int pf8x00_sw_current_table[] = {
156 2100000, 2600000, 3000000, 4500000,
157};
d3795d63
JT
158
159/* Output: 0.4V to 1.8V */
35a93349
AG
160#define PF8XOO_SW1_6_VOLTAGE_NUM 0xB2
161static const struct linear_range pf8x00_sw1_to_6_voltages[] = {
162 REGULATOR_LINEAR_RANGE(400000, 0x00, 0xB0, 6250),
163 REGULATOR_LINEAR_RANGE(1800000, 0xB1, 0xB1, 0),
d3795d63
JT
164};
165
166/* Output: 1.0V to 4.1V */
167static const int pf8x00_sw7_voltages[] = {
168 1000000, 1100000, 1200000, 1250000, 1300000, 1350000, 1500000, 1600000,
169 1800000, 1850000, 2000000, 2100000, 2150000, 2250000, 2300000, 2400000,
170 2500000, 2800000, 3150000, 3200000, 3250000, 3300000, 3350000, 3400000,
171 3500000, 3800000, 4000000, 4100000, 4100000, 4100000, 4100000, 4100000,
172};
173
174/* Output: 1.8V, 3.0V, or 3.3V */
175static const int pf8x00_vsnvs_voltages[] = {
176 0, 1800000, 3000000, 3300000,
177};
178
245f5f65 179static void swxilim_select(struct pf8x00_chip *chip, int id, int ilim)
d3795d63 180{
d3795d63 181 u8 ilim_sel;
245f5f65 182 u8 reg = PF8X00_SW_BASE(id) + SW_CONFIG2;
d3795d63
JT
183
184 switch (ilim) {
185 case 2100:
186 ilim_sel = SWXILIM_2100_MA;
187 break;
188 case 2600:
189 ilim_sel = SWXILIM_2600_MA;
190 break;
191 case 3000:
192 ilim_sel = SWXILIM_3000_MA;
193 break;
194 case 4500:
195 ilim_sel = SWXILIM_4500_MA;
196 break;
197 default:
198 ilim_sel = SWXILIM_2100_MA;
199 break;
200 }
201
245f5f65
AG
202 regmap_update_bits(chip->regmap, reg,
203 PF8X00_SWXILIM_MASK,
204 ilim_sel << PF8X00_SWXILIM_SHIFT);
d3795d63
JT
205}
206
245f5f65 207static void handle_ilim_property(struct device_node *np,
d3795d63
JT
208 const struct regulator_desc *desc,
209 struct regulator_config *config)
210{
d3795d63 211 struct pf8x00_chip *chip = config->driver_data;
245f5f65
AG
212 int ret;
213 int val;
214
215 if ((desc->id >= PF8X00_BUCK1) && (desc->id <= PF8X00_BUCK7)) {
216 ret = of_property_read_u32(np, "nxp,ilim-ma", &val);
217 if (ret) {
218 dev_dbg(chip->dev, "unspecified ilim for BUCK%d, use value stored in OTP\n",
219 desc->id - PF8X00_LDO4);
220 return;
221 }
222
223 dev_warn(chip->dev, "nxp,ilim-ma is deprecated, please use regulator-max-microamp\n");
224 swxilim_select(chip, desc->id, val);
225
226 } else
227 dev_warn(chip->dev, "nxp,ilim-ma used with incorrect regulator (%d)\n", desc->id);
d3795d63
JT
228}
229
475a5d85 230static void handle_shift_property(struct device_node *np,
d3795d63
JT
231 const struct regulator_desc *desc,
232 struct regulator_config *config)
233{
475a5d85
AG
234 unsigned char id = desc->id - PF8X00_LDO4;
235 unsigned char reg = PF8X00_SW_BASE(id) + SW_CONFIG2;
d3795d63 236 struct pf8x00_chip *chip = config->driver_data;
475a5d85 237
d3795d63
JT
238 int phase;
239 int val;
240 int ret;
475a5d85
AG
241 if ((desc->id >= PF8X00_BUCK1) && (desc->id <= PF8X00_BUCK7)) {
242 ret = of_property_read_u32(np, "nxp,phase-shift", &val);
243 if (ret) {
244 dev_dbg(chip->dev,
245 "unspecified phase-shift for BUCK%d, using OTP configuration\n",
246 id);
247 return;
248 }
d3795d63 249
475a5d85
AG
250 if (val < 0 || val > 315 || val % 45 != 0) {
251 dev_warn(config->dev,
252 "invalid phase_shift %d for BUCK%d, using OTP configuration\n",
253 val, id);
254 return;
255 }
d3795d63 256
475a5d85 257 phase = val / 45;
d3795d63 258
475a5d85
AG
259 if (phase >= 1)
260 phase -= 1;
261 else
262 phase = PF8X00_SWXPHASE_SHIFT;
263
264 regmap_update_bits(chip->regmap, reg,
265 PF8X00_SWXPHASE_MASK,
266 phase);
267 } else
268 dev_warn(chip->dev, "nxp,phase-shift used with incorrect regulator (%d)\n", id);
269
270}
271
272static int pf8x00_of_parse_cb(struct device_node *np,
273 const struct regulator_desc *desc,
274 struct regulator_config *config)
275{
d3795d63 276
475a5d85
AG
277 handle_ilim_property(np, desc, config);
278 handle_shift_property(np, desc, config);
d3795d63
JT
279
280 return 0;
281}
282
7fefe72b
CF
283static int pf8x00_suspend_enable(struct regulator_dev *rdev)
284{
285 struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
286 struct regmap *rmap = rdev_get_regmap(rdev);
287
288 return regmap_update_bits(rmap, regl->suspend_enable_reg,
289 regl->suspend_enable_mask,
290 regl->suspend_enable_mask);
291}
292
293static int pf8x00_suspend_disable(struct regulator_dev *rdev)
294{
295 struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
296 struct regmap *rmap = rdev_get_regmap(rdev);
297
298 return regmap_update_bits(rmap, regl->suspend_enable_reg,
299 regl->suspend_enable_mask, 0);
300}
301
302static int pf8x00_set_suspend_voltage(struct regulator_dev *rdev, int uV)
303{
304 struct pf8x00_regulator_data *regl = rdev_get_drvdata(rdev);
305 int ret;
306
307 if (regl->suspend_voltage_cache == uV)
308 return 0;
309
310 ret = regulator_map_voltage_iterate(rdev, uV, uV);
311 if (ret < 0) {
312 dev_err(rdev_get_dev(rdev), "failed to map %i uV\n", uV);
313 return ret;
d3795d63
JT
314 }
315
7fefe72b
CF
316 dev_dbg(rdev_get_dev(rdev), "uV: %i, reg: 0x%x, msk: 0x%x, val: 0x%x\n",
317 uV, regl->suspend_voltage_reg, regl->desc.vsel_mask, ret);
318 ret = regmap_update_bits(rdev->regmap, regl->suspend_voltage_reg,
319 regl->desc.vsel_mask, ret);
320 if (ret < 0) {
321 dev_err(rdev_get_dev(rdev), "failed to set %i uV\n", uV);
322 return ret;
d3795d63
JT
323 }
324
7fefe72b 325 regl->suspend_voltage_cache = uV;
d3795d63
JT
326
327 return 0;
328}
329
330static const struct regulator_ops pf8x00_ldo_ops = {
331 .enable = regulator_enable_regmap,
332 .disable = regulator_disable_regmap,
333 .is_enabled = regulator_is_enabled_regmap,
334 .list_voltage = regulator_list_voltage_table,
335 .set_voltage_sel = regulator_set_voltage_sel_regmap,
336 .get_voltage_sel = regulator_get_voltage_sel_regmap,
7fefe72b
CF
337 .set_suspend_enable = pf8x00_suspend_enable,
338 .set_suspend_disable = pf8x00_suspend_disable,
339 .set_suspend_voltage = pf8x00_set_suspend_voltage,
d3795d63
JT
340};
341
35a93349
AG
342
343static const struct regulator_ops pf8x00_buck1_6_ops = {
344 .enable = regulator_enable_regmap,
345 .disable = regulator_disable_regmap,
346 .is_enabled = regulator_is_enabled_regmap,
347 .list_voltage = regulator_list_voltage_linear_range,
348 .set_voltage_sel = regulator_set_voltage_sel_regmap,
349 .get_voltage_sel = regulator_get_voltage_sel_regmap,
350 .get_current_limit = regulator_get_current_limit_regmap,
351 .set_current_limit = regulator_set_current_limit_regmap,
7fefe72b
CF
352 .set_suspend_enable = pf8x00_suspend_enable,
353 .set_suspend_disable = pf8x00_suspend_disable,
354 .set_suspend_voltage = pf8x00_set_suspend_voltage,
d3795d63
JT
355};
356
35a93349 357static const struct regulator_ops pf8x00_buck7_ops = {
d3795d63
JT
358 .enable = regulator_enable_regmap,
359 .disable = regulator_disable_regmap,
360 .is_enabled = regulator_is_enabled_regmap,
361 .list_voltage = regulator_list_voltage_table,
1e50433c 362 .map_voltage = regulator_map_voltage_ascend,
d3795d63
JT
363 .set_voltage_sel = regulator_set_voltage_sel_regmap,
364 .get_voltage_sel = regulator_get_voltage_sel_regmap,
245f5f65
AG
365 .get_current_limit = regulator_get_current_limit_regmap,
366 .set_current_limit = regulator_set_current_limit_regmap,
7fefe72b
CF
367 .set_suspend_enable = pf8x00_suspend_enable,
368 .set_suspend_disable = pf8x00_suspend_disable,
d3795d63
JT
369};
370
371static const struct regulator_ops pf8x00_vsnvs_ops = {
372 .enable = regulator_enable_regmap,
373 .disable = regulator_disable_regmap,
374 .is_enabled = regulator_is_enabled_regmap,
375 .list_voltage = regulator_list_voltage_table,
376 .map_voltage = regulator_map_voltage_ascend,
377 .set_voltage_sel = regulator_set_voltage_sel_regmap,
378 .get_voltage_sel = regulator_get_voltage_sel_regmap,
379};
380
381#define PF8X00LDO(_id, _name, base, voltages) \
382 [PF8X00_LDO ## _id] = { \
383 .desc = { \
384 .name = _name, \
385 .of_match = _name, \
386 .regulators_node = "regulators", \
387 .n_voltages = ARRAY_SIZE(voltages), \
388 .ops = &pf8x00_ldo_ops, \
389 .type = REGULATOR_VOLTAGE, \
390 .id = PF8X00_LDO ## _id, \
391 .owner = THIS_MODULE, \
392 .volt_table = voltages, \
393 .vsel_reg = (base) + LDO_RUN_VOLT, \
394 .vsel_mask = 0xff, \
395 .enable_reg = (base) + LDO_CONFIG2, \
396 .enable_val = 0x2, \
397 .disable_val = 0x0, \
398 .enable_mask = 2, \
399 }, \
7fefe72b
CF
400 .suspend_enable_reg = (base) + LDO_CONFIG2, \
401 .suspend_enable_mask = 1, \
402 .suspend_voltage_reg = (base) + LDO_STBY_VOLT, \
d3795d63
JT
403 }
404
405#define PF8X00BUCK(_id, _name, base, voltages) \
406 [PF8X00_BUCK ## _id] = { \
407 .desc = { \
408 .name = _name, \
409 .of_match = _name, \
410 .regulators_node = "regulators", \
411 .of_parse_cb = pf8x00_of_parse_cb, \
35a93349
AG
412 .n_voltages = PF8XOO_SW1_6_VOLTAGE_NUM, \
413 .ops = &pf8x00_buck1_6_ops, \
d3795d63
JT
414 .type = REGULATOR_VOLTAGE, \
415 .id = PF8X00_BUCK ## _id, \
416 .owner = THIS_MODULE, \
4288b4cc 417 .ramp_delay = 19000, \
35a93349
AG
418 .linear_ranges = pf8x00_sw1_to_6_voltages, \
419 .n_linear_ranges = \
420 ARRAY_SIZE(pf8x00_sw1_to_6_voltages), \
421 .vsel_reg = (base) + SW_RUN_VOLT, \
422 .vsel_mask = 0xff, \
423 .curr_table = pf8x00_sw_current_table, \
424 .n_current_limits = \
425 ARRAY_SIZE(pf8x00_sw_current_table), \
426 .csel_reg = (base) + SW_CONFIG2, \
427 .csel_mask = PF8X00_SWXILIM_MASK, \
428 .enable_reg = (base) + SW_MODE1, \
429 .enable_val = 0x3, \
430 .disable_val = 0x0, \
431 .enable_mask = 0x3, \
432 .enable_time = 500, \
433 }, \
7fefe72b
CF
434 .suspend_enable_reg = (base) + SW_MODE1, \
435 .suspend_enable_mask = 0xc, \
436 .suspend_voltage_reg = (base) + SW_STBY_VOLT, \
35a93349
AG
437 }
438
439#define PF8X00BUCK7(_name, base, voltages) \
440 [PF8X00_BUCK7] = { \
441 .desc = { \
442 .name = _name, \
443 .of_match = _name, \
444 .regulators_node = "regulators", \
445 .of_parse_cb = pf8x00_of_parse_cb, \
446 .n_voltages = ARRAY_SIZE(voltages), \
447 .ops = &pf8x00_buck7_ops, \
448 .type = REGULATOR_VOLTAGE, \
449 .id = PF8X00_BUCK7, \
450 .owner = THIS_MODULE, \
4288b4cc 451 .ramp_delay = 19000, \
d3795d63
JT
452 .volt_table = voltages, \
453 .vsel_reg = (base) + SW_RUN_VOLT, \
454 .vsel_mask = 0xff, \
245f5f65
AG
455 .curr_table = pf8x00_sw_current_table, \
456 .n_current_limits = \
457 ARRAY_SIZE(pf8x00_sw_current_table), \
458 .csel_reg = (base) + SW_CONFIG2, \
459 .csel_mask = PF8X00_SWXILIM_MASK, \
d3795d63
JT
460 .enable_reg = (base) + SW_MODE1, \
461 .enable_val = 0x3, \
462 .disable_val = 0x0, \
463 .enable_mask = 0x3, \
464 .enable_time = 500, \
465 }, \
466 }
467
35a93349 468
d3795d63
JT
469#define PF8X00VSNVS(_name, base, voltages) \
470 [PF8X00_VSNVS] = { \
471 .desc = { \
472 .name = _name, \
473 .of_match = _name, \
474 .regulators_node = "regulators", \
475 .n_voltages = ARRAY_SIZE(voltages), \
476 .ops = &pf8x00_vsnvs_ops, \
477 .type = REGULATOR_VOLTAGE, \
478 .id = PF8X00_VSNVS, \
479 .owner = THIS_MODULE, \
480 .volt_table = voltages, \
481 .vsel_reg = (base), \
482 .vsel_mask = 0x3, \
483 }, \
484 }
485
7fefe72b 486static struct pf8x00_regulator_data pf8x00_regs_data[PF8X00_MAX_REGULATORS] = {
d3795d63
JT
487 PF8X00LDO(1, "ldo1", PF8X00_LDO_BASE(PF8X00_LDO1), pf8x00_ldo_voltages),
488 PF8X00LDO(2, "ldo2", PF8X00_LDO_BASE(PF8X00_LDO2), pf8x00_ldo_voltages),
489 PF8X00LDO(3, "ldo3", PF8X00_LDO_BASE(PF8X00_LDO3), pf8x00_ldo_voltages),
490 PF8X00LDO(4, "ldo4", PF8X00_LDO_BASE(PF8X00_LDO4), pf8x00_ldo_voltages),
491 PF8X00BUCK(1, "buck1", PF8X00_SW_BASE(PF8X00_BUCK1), pf8x00_sw1_to_6_voltages),
492 PF8X00BUCK(2, "buck2", PF8X00_SW_BASE(PF8X00_BUCK2), pf8x00_sw1_to_6_voltages),
493 PF8X00BUCK(3, "buck3", PF8X00_SW_BASE(PF8X00_BUCK3), pf8x00_sw1_to_6_voltages),
494 PF8X00BUCK(4, "buck4", PF8X00_SW_BASE(PF8X00_BUCK4), pf8x00_sw1_to_6_voltages),
495 PF8X00BUCK(5, "buck5", PF8X00_SW_BASE(PF8X00_BUCK5), pf8x00_sw1_to_6_voltages),
496 PF8X00BUCK(6, "buck6", PF8X00_SW_BASE(PF8X00_BUCK6), pf8x00_sw1_to_6_voltages),
35a93349 497 PF8X00BUCK7("buck7", PF8X00_SW_BASE(PF8X00_BUCK7), pf8x00_sw7_voltages),
d3795d63
JT
498 PF8X00VSNVS("vsnvs", PF8X00_VSNVS_CONFIG1, pf8x00_vsnvs_voltages),
499};
500
501static int pf8x00_identify(struct pf8x00_chip *chip)
502{
503 unsigned int value;
504 u8 dev_fam, dev_id;
505 const char *name = NULL;
506 int ret;
507
508 ret = regmap_read(chip->regmap, PF8X00_DEVICEID, &value);
509 if (ret) {
510 dev_err(chip->dev, "failed to read chip family\n");
511 return ret;
512 }
513
514 dev_fam = value & PF8X00_DEVICE_FAM_MASK;
515 switch (dev_fam) {
516 case PF8X00_FAM:
517 break;
518 default:
519 dev_err(chip->dev,
520 "Chip 0x%x is not from PF8X00 family\n", dev_fam);
521 return ret;
522 }
523
524 dev_id = value & PF8X00_DEVICE_ID_MASK;
525 switch (dev_id) {
526 case PF8100:
527 name = "PF8100";
528 break;
529 case PF8121A:
530 name = "PF8121A";
531 break;
532 case PF8200:
64f09ea1 533 name = "PF8200";
d3795d63
JT
534 break;
535 default:
536 dev_err(chip->dev, "Unknown pf8x00 device id 0x%x\n", dev_id);
537 return -ENODEV;
538 }
539
540 dev_info(chip->dev, "%s PMIC found.\n", name);
541
542 return 0;
543}
544
545static int pf8x00_i2c_probe(struct i2c_client *client)
546{
547 struct regulator_config config = { NULL, };
548 struct pf8x00_chip *chip;
549 int id;
550 int ret;
551
552 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
553 if (!chip)
554 return -ENOMEM;
555
556 i2c_set_clientdata(client, chip);
557 chip->dev = &client->dev;
558
559 chip->regmap = devm_regmap_init_i2c(client, &pf8x00_regmap_config);
560 if (IS_ERR(chip->regmap)) {
561 ret = PTR_ERR(chip->regmap);
562 dev_err(&client->dev,
563 "regmap allocation failed with err %d\n", ret);
564 return ret;
565 }
566
567 ret = pf8x00_identify(chip);
568 if (ret)
569 return ret;
570
7fefe72b
CF
571 for (id = 0; id < ARRAY_SIZE(pf8x00_regs_data); id++) {
572 struct pf8x00_regulator_data *data = &pf8x00_regs_data[id];
d3795d63
JT
573 struct regulator_dev *rdev;
574
575 config.dev = chip->dev;
7fefe72b 576 config.driver_data = data;
d3795d63
JT
577 config.regmap = chip->regmap;
578
579 rdev = devm_regulator_register(&client->dev, &data->desc, &config);
580 if (IS_ERR(rdev)) {
581 dev_err(&client->dev,
582 "failed to register %s regulator\n", data->desc.name);
583 return PTR_ERR(rdev);
584 }
d3795d63
JT
585 }
586
587 return 0;
588}
589
590static const struct of_device_id pf8x00_dt_ids[] = {
df9716ec
MB
591 { .compatible = "nxp,pf8100",},
592 { .compatible = "nxp,pf8121a",},
593 { .compatible = "nxp,pf8200",},
d3795d63
JT
594 { }
595};
596MODULE_DEVICE_TABLE(of, pf8x00_dt_ids);
597
598static const struct i2c_device_id pf8x00_i2c_id[] = {
df9716ec
MB
599 { "pf8100", 0 },
600 { "pf8121a", 0 },
601 { "pf8200", 0 },
d3795d63
JT
602 {},
603};
604MODULE_DEVICE_TABLE(i2c, pf8x00_i2c_id);
605
606static struct i2c_driver pf8x00_regulator_driver = {
607 .id_table = pf8x00_i2c_id,
608 .driver = {
609 .name = "pf8x00",
46600ab1 610 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
d3795d63
JT
611 .of_match_table = pf8x00_dt_ids,
612 },
964e1865 613 .probe = pf8x00_i2c_probe,
d3795d63
JT
614};
615module_i2c_driver(pf8x00_regulator_driver);
616
617MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
618MODULE_AUTHOR("Troy Kisky <troy.kisky@boundarydevices.com>");
619MODULE_DESCRIPTION("Regulator Driver for NXP's PF8100/PF8121A/PF8200 PMIC");
620MODULE_LICENSE("GPL v2");