Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-2.6-block.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++) {
229 if (chip->rdev[i] != NULL) {
275513b7 230 regulator_lock(chip->rdev[i]);
c90456e3
JB
231 regulator_notifier_call_chain(chip->rdev[i],
232 REGULATOR_EVENT_UNDER_VOLTAGE,
233 NULL);
275513b7 234 regulator_unlock(chip->rdev[i]);
c90456e3
JB
235 }
236 }
237
623f7b93
JB
238 err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
239 PV88090_E_VDD_FLT);
c90456e3
JB
240 if (err < 0)
241 goto error_i2c;
242
243 ret = IRQ_HANDLED;
244 }
245
246 if (reg_val & PV88090_E_OVER_TEMP) {
247 for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
248 if (chip->rdev[i] != NULL) {
275513b7 249 regulator_lock(chip->rdev[i]);
c90456e3
JB
250 regulator_notifier_call_chain(chip->rdev[i],
251 REGULATOR_EVENT_OVER_TEMP,
252 NULL);
275513b7 253 regulator_unlock(chip->rdev[i]);
c90456e3
JB
254 }
255 }
256
623f7b93
JB
257 err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
258 PV88090_E_OVER_TEMP);
c90456e3
JB
259 if (err < 0)
260 goto error_i2c;
261
262 ret = IRQ_HANDLED;
263 }
264
265 return ret;
266
267error_i2c:
268 dev_err(chip->dev, "I2C error : %d\n", err);
269 return IRQ_NONE;
270}
271
272/*
273 * I2C driver interface functions
274 */
275static int pv88090_i2c_probe(struct i2c_client *i2c,
276 const struct i2c_device_id *id)
277{
278 struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
279 struct pv88090 *chip;
280 struct regulator_config config = { };
281 int error, i, ret = 0;
282 unsigned int conf2, range, index;
283
284 chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88090), GFP_KERNEL);
285 if (!chip)
286 return -ENOMEM;
287
288 chip->dev = &i2c->dev;
289 chip->regmap = devm_regmap_init_i2c(i2c, &pv88090_regmap_config);
290 if (IS_ERR(chip->regmap)) {
291 error = PTR_ERR(chip->regmap);
292 dev_err(chip->dev, "Failed to allocate register map: %d\n",
293 error);
294 return error;
295 }
296
297 i2c_set_clientdata(i2c, chip);
298
299 if (i2c->irq != 0) {
300 ret = regmap_write(chip->regmap, PV88090_REG_MASK_A, 0xFF);
301 if (ret < 0) {
302 dev_err(chip->dev,
303 "Failed to mask A reg: %d\n", ret);
304 return ret;
305 }
306
307 ret = regmap_write(chip->regmap, PV88090_REG_MASK_B, 0xFF);
308 if (ret < 0) {
309 dev_err(chip->dev,
310 "Failed to mask B reg: %d\n", ret);
311 return ret;
312 }
313
ecee988a 314 ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
c90456e3
JB
315 pv88090_irq_handler,
316 IRQF_TRIGGER_LOW|IRQF_ONESHOT,
317 "pv88090", chip);
318 if (ret != 0) {
319 dev_err(chip->dev, "Failed to request IRQ: %d\n",
320 i2c->irq);
321 return ret;
322 }
323
324 ret = regmap_update_bits(chip->regmap, PV88090_REG_MASK_A,
325 PV88090_M_VDD_FLT | PV88090_M_OVER_TEMP, 0);
326 if (ret < 0) {
327 dev_err(chip->dev,
328 "Failed to update mask reg: %d\n", ret);
329 return ret;
330 }
331
332 } else {
333 dev_warn(chip->dev, "No IRQ configured\n");
334 }
335
336 config.dev = chip->dev;
337 config.regmap = chip->regmap;
338
339 for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
340 if (init_data)
341 config.init_data = &init_data[i];
342
343 if (i == PV88090_ID_BUCK2 || i == PV88090_ID_BUCK3) {
344 ret = regmap_read(chip->regmap,
345 pv88090_regulator_info[i].conf2, &conf2);
346 if (ret < 0)
347 return ret;
348
d761c906
DC
349 conf2 = (conf2 >> PV88090_BUCK_VDAC_RANGE_SHIFT) &
350 PV88090_BUCK_VDAC_RANGE_MASK;
c90456e3
JB
351
352 ret = regmap_read(chip->regmap,
353 PV88090_REG_BUCK_FOLD_RANGE, &range);
354 if (ret < 0)
355 return ret;
356
d761c906 357 range = (range >>
8986a119
EJ
358 (PV88090_BUCK_VRANGE_GAIN_SHIFT + i - 1)) &
359 PV88090_BUCK_VRANGE_GAIN_MASK;
c90456e3 360 index = ((range << 1) | conf2);
8986a119
EJ
361 if (index > PV88090_ID_BUCK3) {
362 dev_err(chip->dev,
363 "Invalid index(%d)\n", index);
364 return -EINVAL;
365 }
c90456e3
JB
366
367 pv88090_regulator_info[i].desc.min_uV
368 = pv88090_buck_vol[index].min_uV;
369 pv88090_regulator_info[i].desc.uV_step
370 = pv88090_buck_vol[index].uV_step;
371 pv88090_regulator_info[i].desc.n_voltages
372 = ((pv88090_buck_vol[index].max_uV)
373 - (pv88090_buck_vol[index].min_uV))
374 /(pv88090_buck_vol[index].uV_step) + 1;
375 }
376
377 config.driver_data = (void *)&pv88090_regulator_info[i];
378 chip->rdev[i] = devm_regulator_register(chip->dev,
379 &pv88090_regulator_info[i].desc, &config);
380 if (IS_ERR(chip->rdev[i])) {
381 dev_err(chip->dev,
382 "Failed to register PV88090 regulator\n");
383 return PTR_ERR(chip->rdev[i]);
384 }
385 }
386
387 return 0;
388}
389
390static const struct i2c_device_id pv88090_i2c_id[] = {
391 {"pv88090", 0},
392 {},
393};
394MODULE_DEVICE_TABLE(i2c, pv88090_i2c_id);
395
396#ifdef CONFIG_OF
397static const struct of_device_id pv88090_dt_ids[] = {
398 { .compatible = "pvs,pv88090", .data = &pv88090_i2c_id[0] },
399 {},
400};
401MODULE_DEVICE_TABLE(of, pv88090_dt_ids);
402#endif
403
404static struct i2c_driver pv88090_regulator_driver = {
405 .driver = {
406 .name = "pv88090",
407 .of_match_table = of_match_ptr(pv88090_dt_ids),
408 },
409 .probe = pv88090_i2c_probe,
410 .id_table = pv88090_i2c_id,
411};
412
413module_i2c_driver(pv88090_regulator_driver);
414
415MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
416MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88090");
417MODULE_LICENSE("GPL");