]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/regulator/pv88090-regulator.c
Merge tag 'char-misc-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[mirror_ubuntu-jammy-kernel.git] / drivers / regulator / pv88090-regulator.c
CommitLineData
0ae3b061
AL
1// SPDX-License-Identifier: GPL-2.0+
2//
3// pv88090-regulator.c - Regulator device driver for PV88090
4// Copyright (C) 2015 Powerventure Semiconductor Ltd.
c90456e3
JB
5
6#include <linux/err.h>
c90456e3
JB
7#include <linux/i2c.h>
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/slab.h>
11#include <linux/regulator/driver.h>
12#include <linux/regulator/machine.h>
13#include <linux/regmap.h>
14#include <linux/irq.h>
15#include <linux/interrupt.h>
16#include <linux/regulator/of_regulator.h>
c90456e3
JB
17#include "pv88090-regulator.h"
18
19#define PV88090_MAX_REGULATORS 5
20
21/* PV88090 REGULATOR IDs */
22enum {
23 /* BUCKs */
24 PV88090_ID_BUCK1,
25 PV88090_ID_BUCK2,
26 PV88090_ID_BUCK3,
27
28 /* LDOs */
29 PV88090_ID_LDO1,
30 PV88090_ID_LDO2,
31};
32
33struct pv88090_regulator {
34 struct regulator_desc desc;
c90456e3
JB
35 unsigned int conf;
36 unsigned int conf2;
37};
38
39struct pv88090 {
40 struct device *dev;
41 struct regmap *regmap;
42 struct regulator_dev *rdev[PV88090_MAX_REGULATORS];
43};
44
45struct pv88090_buck_voltage {
46 int min_uV;
47 int max_uV;
48 int uV_step;
49};
50
51static const struct regmap_config pv88090_regmap_config = {
52 .reg_bits = 8,
53 .val_bits = 8,
54};
55
56/* Current limits array (in uA) for BUCK1, BUCK2, BUCK3.
57 * Entry indexes corresponds to register values.
58 */
59
f4afd05e 60static const unsigned int pv88090_buck1_limits[] = {
c90456e3
JB
61 220000, 440000, 660000, 880000, 1100000, 1320000, 1540000, 1760000,
62 1980000, 2200000, 2420000, 2640000, 2860000, 3080000, 3300000, 3520000,
63 3740000, 3960000, 4180000, 4400000, 4620000, 4840000, 5060000, 5280000,
64 5500000, 5720000, 5940000, 6160000, 6380000, 6600000, 6820000, 7040000
65};
66
f4afd05e 67static const unsigned int pv88090_buck23_limits[] = {
c90456e3
JB
68 1496000, 2393000, 3291000, 4189000
69};
70
71static const struct pv88090_buck_voltage pv88090_buck_vol[3] = {
72 {
73 .min_uV = 600000,
74 .max_uV = 1393750,
75 .uV_step = 6250,
76 },
77
78 {
79 .min_uV = 1400000,
80 .max_uV = 2193750,
81 .uV_step = 6250,
82 },
83 {
84 .min_uV = 1250000,
85 .max_uV = 2837500,
86 .uV_step = 12500,
87 },
88};
89
90static unsigned int pv88090_buck_get_mode(struct regulator_dev *rdev)
91{
92 struct pv88090_regulator *info = rdev_get_drvdata(rdev);
93 unsigned int data;
94 int ret, mode = 0;
95
96 ret = regmap_read(rdev->regmap, info->conf, &data);
97 if (ret < 0)
98 return ret;
99
100 switch (data & PV88090_BUCK1_MODE_MASK) {
101 case PV88090_BUCK_MODE_SYNC:
102 mode = REGULATOR_MODE_FAST;
103 break;
104 case PV88090_BUCK_MODE_AUTO:
105 mode = REGULATOR_MODE_NORMAL;
106 break;
107 case PV88090_BUCK_MODE_SLEEP:
108 mode = REGULATOR_MODE_STANDBY;
109 break;
110 }
111
112 return mode;
113}
114
115static int pv88090_buck_set_mode(struct regulator_dev *rdev,
116 unsigned int mode)
117{
118 struct pv88090_regulator *info = rdev_get_drvdata(rdev);
119 int val = 0;
120
121 switch (mode) {
122 case REGULATOR_MODE_FAST:
123 val = PV88090_BUCK_MODE_SYNC;
124 break;
125 case REGULATOR_MODE_NORMAL:
126 val = PV88090_BUCK_MODE_AUTO;
127 break;
128 case REGULATOR_MODE_STANDBY:
129 val = PV88090_BUCK_MODE_SLEEP;
130 break;
131 default:
132 return -EINVAL;
133 }
134
135 return regmap_update_bits(rdev->regmap, info->conf,
136 PV88090_BUCK1_MODE_MASK, val);
137}
138
36fe20c7 139static const struct regulator_ops pv88090_buck_ops = {
c90456e3
JB
140 .get_mode = pv88090_buck_get_mode,
141 .set_mode = pv88090_buck_set_mode,
142 .enable = regulator_enable_regmap,
143 .disable = regulator_disable_regmap,
144 .is_enabled = regulator_is_enabled_regmap,
145 .set_voltage_sel = regulator_set_voltage_sel_regmap,
146 .get_voltage_sel = regulator_get_voltage_sel_regmap,
147 .list_voltage = regulator_list_voltage_linear,
f4afd05e
AL
148 .set_current_limit = regulator_set_current_limit_regmap,
149 .get_current_limit = regulator_get_current_limit_regmap,
c90456e3
JB
150};
151
36fe20c7 152static const struct regulator_ops pv88090_ldo_ops = {
c90456e3
JB
153 .enable = regulator_enable_regmap,
154 .disable = regulator_disable_regmap,
155 .is_enabled = regulator_is_enabled_regmap,
156 .set_voltage_sel = regulator_set_voltage_sel_regmap,
157 .get_voltage_sel = regulator_get_voltage_sel_regmap,
158 .list_voltage = regulator_list_voltage_linear,
159};
160
161#define PV88090_BUCK(chip, regl_name, min, step, max, limits_array) \
162{\
163 .desc = {\
164 .id = chip##_ID_##regl_name,\
165 .name = __stringify(chip##_##regl_name),\
166 .of_match = of_match_ptr(#regl_name),\
167 .regulators_node = of_match_ptr("regulators"),\
168 .type = REGULATOR_VOLTAGE,\
169 .owner = THIS_MODULE,\
170 .ops = &pv88090_buck_ops,\
171 .min_uV = min, \
172 .uV_step = step, \
173 .n_voltages = ((max) - (min))/(step) + 1, \
174 .enable_reg = PV88090_REG_##regl_name##_CONF0, \
175 .enable_mask = PV88090_##regl_name##_EN, \
176 .vsel_reg = PV88090_REG_##regl_name##_CONF0, \
177 .vsel_mask = PV88090_V##regl_name##_MASK, \
f4afd05e
AL
178 .curr_table = limits_array, \
179 .n_current_limits = ARRAY_SIZE(limits_array), \
180 .csel_reg = PV88090_REG_##regl_name##_CONF1, \
181 .csel_mask = PV88090_##regl_name##_ILIM_MASK, \
c90456e3 182 },\
c90456e3
JB
183 .conf = PV88090_REG_##regl_name##_CONF1, \
184 .conf2 = PV88090_REG_##regl_name##_CONF2, \
185}
186
187#define PV88090_LDO(chip, regl_name, min, step, max) \
188{\
189 .desc = {\
190 .id = chip##_ID_##regl_name,\
191 .name = __stringify(chip##_##regl_name),\
192 .of_match = of_match_ptr(#regl_name),\
193 .regulators_node = of_match_ptr("regulators"),\
194 .type = REGULATOR_VOLTAGE,\
195 .owner = THIS_MODULE,\
196 .ops = &pv88090_ldo_ops,\
197 .min_uV = min, \
198 .uV_step = step, \
199 .n_voltages = ((max) - (min))/(step) + 1, \
200 .enable_reg = PV88090_REG_##regl_name##_CONT, \
201 .enable_mask = PV88090_##regl_name##_EN, \
202 .vsel_reg = PV88090_REG_##regl_name##_CONT, \
203 .vsel_mask = PV88090_V##regl_name##_MASK, \
204 },\
205}
206
207static struct pv88090_regulator pv88090_regulator_info[] = {
208 PV88090_BUCK(PV88090, BUCK1, 600000, 6250, 1393750,
209 pv88090_buck1_limits),
210 PV88090_BUCK(PV88090, BUCK2, 600000, 6250, 1393750,
211 pv88090_buck23_limits),
212 PV88090_BUCK(PV88090, BUCK3, 600000, 6250, 1393750,
213 pv88090_buck23_limits),
214 PV88090_LDO(PV88090, LDO1, 1200000, 50000, 4350000),
215 PV88090_LDO(PV88090, LDO2, 650000, 25000, 2225000),
216};
217
218static irqreturn_t pv88090_irq_handler(int irq, void *data)
219{
220 struct pv88090 *chip = data;
221 int i, reg_val, err, ret = IRQ_NONE;
222
223 err = regmap_read(chip->regmap, PV88090_REG_EVENT_A, &reg_val);
224 if (err < 0)
225 goto error_i2c;
226
227 if (reg_val & PV88090_E_VDD_FLT) {
228 for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
e9c142b0 229 if (chip->rdev[i] != NULL)
c90456e3
JB
230 regulator_notifier_call_chain(chip->rdev[i],
231 REGULATOR_EVENT_UNDER_VOLTAGE,
232 NULL);
c90456e3
JB
233 }
234
623f7b93
JB
235 err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
236 PV88090_E_VDD_FLT);
c90456e3
JB
237 if (err < 0)
238 goto error_i2c;
239
240 ret = IRQ_HANDLED;
241 }
242
243 if (reg_val & PV88090_E_OVER_TEMP) {
244 for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
e9c142b0 245 if (chip->rdev[i] != NULL)
c90456e3
JB
246 regulator_notifier_call_chain(chip->rdev[i],
247 REGULATOR_EVENT_OVER_TEMP,
248 NULL);
c90456e3
JB
249 }
250
623f7b93
JB
251 err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
252 PV88090_E_OVER_TEMP);
c90456e3
JB
253 if (err < 0)
254 goto error_i2c;
255
256 ret = IRQ_HANDLED;
257 }
258
259 return ret;
260
261error_i2c:
262 dev_err(chip->dev, "I2C error : %d\n", err);
263 return IRQ_NONE;
264}
265
266/*
267 * I2C driver interface functions
268 */
77e29598 269static int pv88090_i2c_probe(struct i2c_client *i2c)
c90456e3
JB
270{
271 struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
272 struct pv88090 *chip;
273 struct regulator_config config = { };
274 int error, i, ret = 0;
275 unsigned int conf2, range, index;
276
277 chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88090), GFP_KERNEL);
278 if (!chip)
279 return -ENOMEM;
280
281 chip->dev = &i2c->dev;
282 chip->regmap = devm_regmap_init_i2c(i2c, &pv88090_regmap_config);
283 if (IS_ERR(chip->regmap)) {
284 error = PTR_ERR(chip->regmap);
285 dev_err(chip->dev, "Failed to allocate register map: %d\n",
286 error);
287 return error;
288 }
289
290 i2c_set_clientdata(i2c, chip);
291
292 if (i2c->irq != 0) {
293 ret = regmap_write(chip->regmap, PV88090_REG_MASK_A, 0xFF);
294 if (ret < 0) {
295 dev_err(chip->dev,
296 "Failed to mask A reg: %d\n", ret);
297 return ret;
298 }
299
300 ret = regmap_write(chip->regmap, PV88090_REG_MASK_B, 0xFF);
301 if (ret < 0) {
302 dev_err(chip->dev,
303 "Failed to mask B reg: %d\n", ret);
304 return ret;
305 }
306
ecee988a 307 ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
c90456e3
JB
308 pv88090_irq_handler,
309 IRQF_TRIGGER_LOW|IRQF_ONESHOT,
310 "pv88090", chip);
311 if (ret != 0) {
312 dev_err(chip->dev, "Failed to request IRQ: %d\n",
313 i2c->irq);
314 return ret;
315 }
316
317 ret = regmap_update_bits(chip->regmap, PV88090_REG_MASK_A,
318 PV88090_M_VDD_FLT | PV88090_M_OVER_TEMP, 0);
319 if (ret < 0) {
320 dev_err(chip->dev,
321 "Failed to update mask reg: %d\n", ret);
322 return ret;
323 }
324
325 } else {
326 dev_warn(chip->dev, "No IRQ configured\n");
327 }
328
329 config.dev = chip->dev;
330 config.regmap = chip->regmap;
331
332 for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
333 if (init_data)
334 config.init_data = &init_data[i];
335
336 if (i == PV88090_ID_BUCK2 || i == PV88090_ID_BUCK3) {
337 ret = regmap_read(chip->regmap,
338 pv88090_regulator_info[i].conf2, &conf2);
339 if (ret < 0)
340 return ret;
341
d761c906
DC
342 conf2 = (conf2 >> PV88090_BUCK_VDAC_RANGE_SHIFT) &
343 PV88090_BUCK_VDAC_RANGE_MASK;
c90456e3
JB
344
345 ret = regmap_read(chip->regmap,
346 PV88090_REG_BUCK_FOLD_RANGE, &range);
347 if (ret < 0)
348 return ret;
349
d761c906 350 range = (range >>
8986a119
EJ
351 (PV88090_BUCK_VRANGE_GAIN_SHIFT + i - 1)) &
352 PV88090_BUCK_VRANGE_GAIN_MASK;
c90456e3 353 index = ((range << 1) | conf2);
8986a119
EJ
354 if (index > PV88090_ID_BUCK3) {
355 dev_err(chip->dev,
356 "Invalid index(%d)\n", index);
357 return -EINVAL;
358 }
c90456e3
JB
359
360 pv88090_regulator_info[i].desc.min_uV
361 = pv88090_buck_vol[index].min_uV;
362 pv88090_regulator_info[i].desc.uV_step
363 = pv88090_buck_vol[index].uV_step;
364 pv88090_regulator_info[i].desc.n_voltages
365 = ((pv88090_buck_vol[index].max_uV)
366 - (pv88090_buck_vol[index].min_uV))
367 /(pv88090_buck_vol[index].uV_step) + 1;
368 }
369
370 config.driver_data = (void *)&pv88090_regulator_info[i];
371 chip->rdev[i] = devm_regulator_register(chip->dev,
372 &pv88090_regulator_info[i].desc, &config);
373 if (IS_ERR(chip->rdev[i])) {
374 dev_err(chip->dev,
375 "Failed to register PV88090 regulator\n");
376 return PTR_ERR(chip->rdev[i]);
377 }
378 }
379
380 return 0;
381}
382
383static const struct i2c_device_id pv88090_i2c_id[] = {
384 {"pv88090", 0},
385 {},
386};
387MODULE_DEVICE_TABLE(i2c, pv88090_i2c_id);
388
389#ifdef CONFIG_OF
390static const struct of_device_id pv88090_dt_ids[] = {
391 { .compatible = "pvs,pv88090", .data = &pv88090_i2c_id[0] },
392 {},
393};
394MODULE_DEVICE_TABLE(of, pv88090_dt_ids);
395#endif
396
397static struct i2c_driver pv88090_regulator_driver = {
398 .driver = {
399 .name = "pv88090",
400 .of_match_table = of_match_ptr(pv88090_dt_ids),
401 },
77e29598 402 .probe_new = pv88090_i2c_probe,
c90456e3
JB
403 .id_table = pv88090_i2c_id,
404};
405
406module_i2c_driver(pv88090_regulator_driver);
407
408MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
409MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88090");
410MODULE_LICENSE("GPL");