diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/regulator/max77663-regulator.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/regulator/max77663-regulator.c')
-rw-r--r-- | drivers/regulator/max77663-regulator.c | 928 |
1 files changed, 928 insertions, 0 deletions
diff --git a/drivers/regulator/max77663-regulator.c b/drivers/regulator/max77663-regulator.c new file mode 100644 index 00000000000..dca8ece4c43 --- /dev/null +++ b/drivers/regulator/max77663-regulator.c | |||
@@ -0,0 +1,928 @@ | |||
1 | /* | ||
2 | * drivers/regulator/max77663-regulator.c | ||
3 | * Maxim LDO and Buck regulators driver | ||
4 | * | ||
5 | * Copyright 2011-2012 Maxim Integrated Products, Inc. | ||
6 | * Copyright (C) 2011-2012 NVIDIA Corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of the | ||
11 | * License, or (at your option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/err.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/debugfs.h> | ||
22 | #include <linux/uaccess.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/mfd/core.h> | ||
25 | #include <linux/mfd/max77663-core.h> | ||
26 | #include <linux/regulator/driver.h> | ||
27 | #include <linux/regulator/machine.h> | ||
28 | #include <linux/regulator/max77663-regulator.h> | ||
29 | |||
30 | /* Regulator types */ | ||
31 | #define REGULATOR_TYPE_SD 0 | ||
32 | #define REGULATOR_TYPE_LDO_N 1 | ||
33 | #define REGULATOR_TYPE_LDO_P 2 | ||
34 | |||
35 | /* SD and LDO Registers */ | ||
36 | #define MAX77663_REG_SD0 0x16 | ||
37 | #define MAX77663_REG_SD1 0x17 | ||
38 | #define MAX77663_REG_SD2 0x18 | ||
39 | #define MAX77663_REG_SD3 0x19 | ||
40 | #define MAX77663_REG_SD4 0x1A | ||
41 | #define MAX77663_REG_DVSSD0 0x1B | ||
42 | #define MAX77663_REG_DVSSD1 0x1C | ||
43 | #define MAX77663_REG_SD0_CFG 0x1D | ||
44 | #define MAX77663_REG_DVSSD0_CFG MAX77663_REG_SD0_CFG | ||
45 | #define MAX77663_REG_SD1_CFG 0x1E | ||
46 | #define MAX77663_REG_DVSSD1_CFG MAX77663_REG_SD1_CFG | ||
47 | #define MAX77663_REG_SD2_CFG 0x1F | ||
48 | #define MAX77663_REG_SD3_CFG 0x20 | ||
49 | #define MAX77663_REG_SD4_CFG 0x21 | ||
50 | #define MAX77663_REG_LDO0_CFG 0x23 | ||
51 | #define MAX77663_REG_LDO0_CFG2 0x24 | ||
52 | #define MAX77663_REG_LDO1_CFG 0x25 | ||
53 | #define MAX77663_REG_LDO1_CFG2 0x26 | ||
54 | #define MAX77663_REG_LDO2_CFG 0x27 | ||
55 | #define MAX77663_REG_LDO2_CFG2 0x28 | ||
56 | #define MAX77663_REG_LDO3_CFG 0x29 | ||
57 | #define MAX77663_REG_LDO3_CFG2 0x2A | ||
58 | #define MAX77663_REG_LDO4_CFG 0x2B | ||
59 | #define MAX77663_REG_LDO4_CFG2 0x2C | ||
60 | #define MAX77663_REG_LDO5_CFG 0x2D | ||
61 | #define MAX77663_REG_LDO5_CFG2 0x2E | ||
62 | #define MAX77663_REG_LDO6_CFG 0x2F | ||
63 | #define MAX77663_REG_LDO6_CFG2 0x30 | ||
64 | #define MAX77663_REG_LDO7_CFG 0x31 | ||
65 | #define MAX77663_REG_LDO7_CFG2 0x32 | ||
66 | #define MAX77663_REG_LDO8_CFG 0x33 | ||
67 | #define MAX77663_REG_LDO8_CFG2 0x34 | ||
68 | #define MAX77663_REG_LDO_CFG3 0x35 | ||
69 | |||
70 | /* Power Mode */ | ||
71 | #define POWER_MODE_NORMAL 3 | ||
72 | #define POWER_MODE_LPM 2 | ||
73 | #define POWER_MODE_GLPM 1 | ||
74 | #define POWER_MODE_DISABLE 0 | ||
75 | #define SD_POWER_MODE_MASK 0x30 | ||
76 | #define SD_POWER_MODE_SHIFT 4 | ||
77 | #define LDO_POWER_MODE_MASK 0xC0 | ||
78 | #define LDO_POWER_MODE_SHIFT 6 | ||
79 | |||
80 | /* SD Slew Rate */ | ||
81 | #define SD_SR_13_75 0 | ||
82 | #define SD_SR_27_5 1 | ||
83 | #define SD_SR_55 2 | ||
84 | #define SD_SR_100 3 | ||
85 | #define SD_SR_MASK 0xC0 | ||
86 | #define SD_SR_SHIFT 6 | ||
87 | |||
88 | /* SD Forced PWM Mode */ | ||
89 | #define SD_FPWM_MASK 0x04 | ||
90 | #define SD_FPWM_SHIFT 2 | ||
91 | |||
92 | /* SD Failling slew rate Active-Discharge Mode */ | ||
93 | #define SD_FSRADE_MASK 0x01 | ||
94 | #define SD_FSRADE_SHIFT 0 | ||
95 | |||
96 | /* LDO Configuration 3 */ | ||
97 | #define TRACK4_MASK 0x20 | ||
98 | #define TRACK4_SHIFT 5 | ||
99 | |||
100 | /* Voltage */ | ||
101 | #define SDX_VOLT_MASK 0xFF | ||
102 | #define SD1_VOLT_MASK 0x3F | ||
103 | #define LDO_VOLT_MASK 0x3F | ||
104 | |||
105 | /* FPS Registers */ | ||
106 | #define MAX77663_REG_FPS_CFG0 0x43 | ||
107 | #define MAX77663_REG_FPS_CFG1 0x44 | ||
108 | #define MAX77663_REG_FPS_CFG2 0x45 | ||
109 | #define MAX77663_REG_FPS_LDO0 0x46 | ||
110 | #define MAX77663_REG_FPS_LDO1 0x47 | ||
111 | #define MAX77663_REG_FPS_LDO2 0x48 | ||
112 | #define MAX77663_REG_FPS_LDO3 0x49 | ||
113 | #define MAX77663_REG_FPS_LDO4 0x4A | ||
114 | #define MAX77663_REG_FPS_LDO5 0x4B | ||
115 | #define MAX77663_REG_FPS_LDO6 0x4C | ||
116 | #define MAX77663_REG_FPS_LDO7 0x4D | ||
117 | #define MAX77663_REG_FPS_LDO8 0x4E | ||
118 | #define MAX77663_REG_FPS_SD0 0x4F | ||
119 | #define MAX77663_REG_FPS_SD1 0x50 | ||
120 | #define MAX77663_REG_FPS_SD2 0x51 | ||
121 | #define MAX77663_REG_FPS_SD3 0x52 | ||
122 | #define MAX77663_REG_FPS_SD4 0x53 | ||
123 | #define MAX77663_REG_FPS_NONE 0 | ||
124 | |||
125 | #define FPS_TIME_PERIOD_MASK 0x38 | ||
126 | #define FPS_TIME_PERIOD_SHIFT 3 | ||
127 | #define FPS_EN_SRC_MASK 0x06 | ||
128 | #define FPS_EN_SRC_SHIFT 1 | ||
129 | #define FPS_SW_EN_MASK 0x01 | ||
130 | #define FPS_SW_EN_SHIFT 0 | ||
131 | #define FPS_SRC_MASK 0xC0 | ||
132 | #define FPS_SRC_SHIFT 6 | ||
133 | #define FPS_PU_PERIOD_MASK 0x38 | ||
134 | #define FPS_PU_PERIOD_SHIFT 3 | ||
135 | #define FPS_PD_PERIOD_MASK 0x07 | ||
136 | #define FPS_PD_PERIOD_SHIFT 0 | ||
137 | |||
138 | /* Chip Identification Register */ | ||
139 | #define MAX77663_REG_CID5 0x5D | ||
140 | |||
141 | #define CID_DIDM_MASK 0xF0 | ||
142 | #define CID_DIDM_SHIFT 4 | ||
143 | |||
144 | #define SD_SAFE_DOWN_UV 50000 /* 50mV */ | ||
145 | |||
146 | enum { | ||
147 | VOLT_REG = 0, | ||
148 | CFG_REG, | ||
149 | FPS_REG, | ||
150 | }; | ||
151 | |||
152 | struct max77663_register { | ||
153 | u8 addr; | ||
154 | u8 val; | ||
155 | }; | ||
156 | |||
157 | struct max77663_regulator { | ||
158 | struct regulator_dev *rdev; | ||
159 | struct device *dev; | ||
160 | struct max77663_regulator_platform_data *pdata; | ||
161 | |||
162 | u8 id; | ||
163 | u8 type; | ||
164 | u32 min_uV; | ||
165 | u32 max_uV; | ||
166 | u32 step_uV; | ||
167 | int safe_down_uV; /* for stable down scaling */ | ||
168 | u32 regulator_mode; | ||
169 | |||
170 | struct max77663_register regs[3]; /* volt, cfg, fps */ | ||
171 | enum max77663_regulator_fps_src fps_src; | ||
172 | |||
173 | u8 volt_mask; | ||
174 | |||
175 | u8 power_mode; | ||
176 | u8 power_mode_mask; | ||
177 | u8 power_mode_shift; | ||
178 | }; | ||
179 | |||
180 | #define fps_src_name(fps_src) \ | ||
181 | (fps_src == FPS_SRC_0 ? "FPS_SRC_0" : \ | ||
182 | fps_src == FPS_SRC_1 ? "FPS_SRC_1" : \ | ||
183 | fps_src == FPS_SRC_2 ? "FPS_SRC_2" : "FPS_SRC_NONE") | ||
184 | |||
185 | static int fps_cfg_init; | ||
186 | static struct max77663_register fps_cfg_regs[] = { | ||
187 | { | ||
188 | .addr = MAX77663_REG_FPS_CFG0, | ||
189 | }, | ||
190 | { | ||
191 | .addr = MAX77663_REG_FPS_CFG1, | ||
192 | }, | ||
193 | { | ||
194 | .addr = MAX77663_REG_FPS_CFG2, | ||
195 | }, | ||
196 | }; | ||
197 | |||
198 | static inline struct max77663_regulator_platform_data | ||
199 | *_to_pdata(struct max77663_regulator *reg) | ||
200 | { | ||
201 | return reg->pdata; | ||
202 | } | ||
203 | |||
204 | static inline struct device *_to_parent(struct max77663_regulator *reg) | ||
205 | { | ||
206 | return reg->dev->parent; | ||
207 | } | ||
208 | |||
209 | static inline int max77663_regulator_cache_write(struct max77663_regulator *reg, | ||
210 | u8 addr, u8 mask, u8 val, u8 *cache) | ||
211 | { | ||
212 | struct device *parent = _to_parent(reg); | ||
213 | u8 new_val; | ||
214 | int ret; | ||
215 | |||
216 | new_val = (*cache & ~mask) | (val & mask); | ||
217 | if (*cache != new_val) { | ||
218 | ret = max77663_write(parent, addr, &new_val, 1, 0); | ||
219 | if (ret < 0) | ||
220 | return ret; | ||
221 | |||
222 | *cache = new_val; | ||
223 | } | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int | ||
228 | max77663_regulator_set_fps_src(struct max77663_regulator *reg, | ||
229 | enum max77663_regulator_fps_src fps_src) | ||
230 | { | ||
231 | int ret; | ||
232 | |||
233 | if ((reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE) || | ||
234 | (reg->fps_src == fps_src)) | ||
235 | return 0; | ||
236 | |||
237 | switch (fps_src) { | ||
238 | case FPS_SRC_0: | ||
239 | case FPS_SRC_1: | ||
240 | case FPS_SRC_2: | ||
241 | case FPS_SRC_NONE: | ||
242 | break; | ||
243 | case FPS_SRC_DEF: | ||
244 | return 0; | ||
245 | default: | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | ret = max77663_regulator_cache_write(reg, reg->regs[FPS_REG].addr, | ||
250 | FPS_SRC_MASK, fps_src << FPS_SRC_SHIFT, | ||
251 | ®->regs[FPS_REG].val); | ||
252 | if (ret < 0) | ||
253 | return ret; | ||
254 | |||
255 | reg->fps_src = fps_src; | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int max77663_regulator_set_fps(struct max77663_regulator *reg) | ||
260 | { | ||
261 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
262 | u8 fps_val = 0, fps_mask = 0; | ||
263 | int ret = 0; | ||
264 | |||
265 | if (reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE) | ||
266 | return 0; | ||
267 | |||
268 | if (reg->fps_src == FPS_SRC_NONE) | ||
269 | return 0; | ||
270 | |||
271 | /* FPS power up period setting */ | ||
272 | if (pdata->fps_pu_period != FPS_POWER_PERIOD_DEF) { | ||
273 | fps_val |= (pdata->fps_pu_period << FPS_PU_PERIOD_SHIFT); | ||
274 | fps_mask |= FPS_PU_PERIOD_MASK; | ||
275 | } | ||
276 | |||
277 | /* FPS power down period setting */ | ||
278 | if (pdata->fps_pd_period != FPS_POWER_PERIOD_DEF) { | ||
279 | fps_val |= (pdata->fps_pd_period << FPS_PD_PERIOD_SHIFT); | ||
280 | fps_mask |= FPS_PD_PERIOD_MASK; | ||
281 | } | ||
282 | |||
283 | if (fps_val) | ||
284 | ret = max77663_regulator_cache_write(reg, | ||
285 | reg->regs[FPS_REG].addr, fps_mask, | ||
286 | fps_val, ®->regs[FPS_REG].val); | ||
287 | |||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int | ||
292 | max77663_regulator_set_fps_cfg(struct max77663_regulator *reg, | ||
293 | struct max77663_regulator_fps_cfg *fps_cfg) | ||
294 | { | ||
295 | u8 val, mask; | ||
296 | |||
297 | if ((fps_cfg->src < FPS_SRC_0) || (fps_cfg->src > FPS_SRC_2)) | ||
298 | return -EINVAL; | ||
299 | |||
300 | val = (fps_cfg->en_src << FPS_EN_SRC_SHIFT); | ||
301 | mask = FPS_EN_SRC_MASK; | ||
302 | |||
303 | if (fps_cfg->time_period != FPS_TIME_PERIOD_DEF) { | ||
304 | val |= (fps_cfg->time_period << FPS_TIME_PERIOD_SHIFT); | ||
305 | mask |= FPS_TIME_PERIOD_MASK; | ||
306 | } | ||
307 | |||
308 | return max77663_regulator_cache_write(reg, | ||
309 | fps_cfg_regs[fps_cfg->src].addr, mask, | ||
310 | val, &fps_cfg_regs[fps_cfg->src].val); | ||
311 | } | ||
312 | |||
313 | static int | ||
314 | max77663_regulator_set_fps_cfgs(struct max77663_regulator *reg, | ||
315 | struct max77663_regulator_fps_cfg *fps_cfgs, | ||
316 | int num_fps_cfgs) | ||
317 | { | ||
318 | struct device *parent = _to_parent(reg); | ||
319 | int i, ret; | ||
320 | |||
321 | if (fps_cfg_init) | ||
322 | return 0; | ||
323 | |||
324 | for (i = 0; i <= FPS_SRC_2; i++) { | ||
325 | ret = max77663_read(parent, fps_cfg_regs[i].addr, | ||
326 | &fps_cfg_regs[i].val, 1, 0); | ||
327 | if (ret < 0) | ||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | for (i = 0; i < num_fps_cfgs; i++) { | ||
332 | ret = max77663_regulator_set_fps_cfg(reg, &fps_cfgs[i]); | ||
333 | if (ret < 0) | ||
334 | return ret; | ||
335 | } | ||
336 | fps_cfg_init = 1; | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static int | ||
342 | max77663_regulator_set_power_mode(struct max77663_regulator *reg, u8 power_mode) | ||
343 | { | ||
344 | u8 mask = reg->power_mode_mask; | ||
345 | u8 shift = reg->power_mode_shift; | ||
346 | int ret; | ||
347 | |||
348 | if (reg->type == REGULATOR_TYPE_SD) | ||
349 | ret = max77663_regulator_cache_write(reg, | ||
350 | reg->regs[CFG_REG].addr, | ||
351 | mask, power_mode << shift, | ||
352 | ®->regs[CFG_REG].val); | ||
353 | else | ||
354 | ret = max77663_regulator_cache_write(reg, | ||
355 | reg->regs[VOLT_REG].addr, | ||
356 | mask, power_mode << shift, | ||
357 | ®->regs[VOLT_REG].val); | ||
358 | |||
359 | if (ret < 0) | ||
360 | return ret; | ||
361 | |||
362 | reg->power_mode = power_mode; | ||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | static u8 max77663_regulator_get_power_mode(struct max77663_regulator *reg) | ||
367 | { | ||
368 | u8 mask = reg->power_mode_mask; | ||
369 | u8 shift = reg->power_mode_shift; | ||
370 | |||
371 | if (reg->type == REGULATOR_TYPE_SD) | ||
372 | reg->power_mode = (reg->regs[CFG_REG].val & mask) >> shift; | ||
373 | else | ||
374 | reg->power_mode = (reg->regs[VOLT_REG].val & mask) >> shift; | ||
375 | |||
376 | return reg->power_mode; | ||
377 | } | ||
378 | |||
379 | static int max77663_regulator_do_set_voltage(struct max77663_regulator *reg, | ||
380 | int min_uV, int max_uV) | ||
381 | { | ||
382 | u8 addr = reg->regs[VOLT_REG].addr; | ||
383 | u8 mask = reg->volt_mask; | ||
384 | u8 *cache = ®->regs[VOLT_REG].val; | ||
385 | u8 val; | ||
386 | int old_uV, new_uV, safe_uV; | ||
387 | int i, steps = 1; | ||
388 | int ret = 0; | ||
389 | |||
390 | if (min_uV < reg->min_uV || max_uV > reg->max_uV) | ||
391 | return -EDOM; | ||
392 | |||
393 | old_uV = (*cache & mask) * reg->step_uV + reg->min_uV; | ||
394 | |||
395 | if ((old_uV > min_uV) && (reg->safe_down_uV >= reg->step_uV)) { | ||
396 | steps = DIV_ROUND_UP(old_uV - min_uV, reg->safe_down_uV); | ||
397 | safe_uV = -reg->safe_down_uV; | ||
398 | } | ||
399 | |||
400 | if (steps == 1) { | ||
401 | val = (min_uV - reg->min_uV) / reg->step_uV; | ||
402 | ret = max77663_regulator_cache_write(reg, addr, mask, val, | ||
403 | cache); | ||
404 | } else { | ||
405 | for (i = 0; i < steps; i++) { | ||
406 | if (abs(min_uV - old_uV) > abs(safe_uV)) | ||
407 | new_uV = old_uV + safe_uV; | ||
408 | else | ||
409 | new_uV = min_uV; | ||
410 | |||
411 | dev_dbg(®->rdev->dev, "do_set_voltage: name=%s, " | ||
412 | "%d/%d, old_uV=%d, new_uV=%d\n", | ||
413 | reg->rdev->desc->name, i + 1, steps, old_uV, | ||
414 | new_uV); | ||
415 | |||
416 | val = (new_uV - reg->min_uV) / reg->step_uV; | ||
417 | ret = max77663_regulator_cache_write(reg, addr, mask, | ||
418 | val, cache); | ||
419 | if (ret < 0) | ||
420 | return ret; | ||
421 | |||
422 | old_uV = new_uV; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | static int max77663_regulator_set_voltage(struct regulator_dev *rdev, | ||
430 | int min_uV, int max_uV, | ||
431 | unsigned *selector) | ||
432 | { | ||
433 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
434 | |||
435 | dev_dbg(&rdev->dev, "set_voltage: name=%s, min_uV=%d, max_uV=%d\n", | ||
436 | rdev->desc->name, min_uV, max_uV); | ||
437 | return max77663_regulator_do_set_voltage(reg, min_uV, max_uV); | ||
438 | } | ||
439 | |||
440 | static int max77663_regulator_get_voltage(struct regulator_dev *rdev) | ||
441 | { | ||
442 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
443 | int volt; | ||
444 | |||
445 | volt = (reg->regs[VOLT_REG].val & reg->volt_mask) | ||
446 | * reg->step_uV + reg->min_uV; | ||
447 | |||
448 | dev_dbg(&rdev->dev, "get_voltage: name=%s, volt=%d, val=0x%02x\n", | ||
449 | rdev->desc->name, volt, reg->regs[VOLT_REG].val); | ||
450 | return volt; | ||
451 | } | ||
452 | |||
453 | static int max77663_regulator_enable(struct regulator_dev *rdev) | ||
454 | { | ||
455 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
456 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
457 | int power_mode = (pdata->flags & GLPM_ENABLE) ? | ||
458 | POWER_MODE_GLPM : POWER_MODE_NORMAL; | ||
459 | |||
460 | if (reg->fps_src != FPS_SRC_NONE) { | ||
461 | dev_dbg(&rdev->dev, "enable: Regulator %s using %s\n", | ||
462 | rdev->desc->name, fps_src_name(reg->fps_src)); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | if ((reg->id == MAX77663_REGULATOR_ID_SD0) | ||
467 | && (pdata->flags & EN2_CTRL_SD0)) { | ||
468 | dev_dbg(&rdev->dev, | ||
469 | "enable: Regulator %s is controlled by EN2\n", | ||
470 | rdev->desc->name); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | /* N-Channel LDOs don't support Low-Power mode. */ | ||
475 | if ((reg->type != REGULATOR_TYPE_LDO_N) && | ||
476 | (reg->regulator_mode == REGULATOR_MODE_STANDBY)) | ||
477 | power_mode = POWER_MODE_LPM; | ||
478 | |||
479 | return max77663_regulator_set_power_mode(reg, power_mode); | ||
480 | } | ||
481 | |||
482 | static int max77663_regulator_disable(struct regulator_dev *rdev) | ||
483 | { | ||
484 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
485 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
486 | int power_mode = POWER_MODE_DISABLE; | ||
487 | |||
488 | if (reg->fps_src != FPS_SRC_NONE) { | ||
489 | dev_dbg(&rdev->dev, "disable: Regulator %s using %s\n", | ||
490 | rdev->desc->name, fps_src_name(reg->fps_src)); | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | if ((reg->id == MAX77663_REGULATOR_ID_SD0) | ||
495 | && (pdata->flags & EN2_CTRL_SD0)) { | ||
496 | dev_dbg(&rdev->dev, | ||
497 | "disable: Regulator %s is controlled by EN2\n", | ||
498 | rdev->desc->name); | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | return max77663_regulator_set_power_mode(reg, power_mode); | ||
503 | } | ||
504 | |||
505 | static int max77663_regulator_is_enabled(struct regulator_dev *rdev) | ||
506 | { | ||
507 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
508 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
509 | int ret = 1; | ||
510 | |||
511 | if (reg->fps_src != FPS_SRC_NONE) { | ||
512 | dev_dbg(&rdev->dev, "is_enable: Regulator %s using %s\n", | ||
513 | rdev->desc->name, fps_src_name(reg->fps_src)); | ||
514 | return 1; | ||
515 | } | ||
516 | |||
517 | if ((reg->id == MAX77663_REGULATOR_ID_SD0) | ||
518 | && (pdata->flags & EN2_CTRL_SD0)) { | ||
519 | dev_dbg(&rdev->dev, | ||
520 | "is_enable: Regulator %s is controlled by EN2\n", | ||
521 | rdev->desc->name); | ||
522 | return 1; | ||
523 | } | ||
524 | |||
525 | if (max77663_regulator_get_power_mode(reg) == POWER_MODE_DISABLE) | ||
526 | ret = 0; | ||
527 | |||
528 | return ret; | ||
529 | } | ||
530 | |||
531 | static int max77663_regulator_set_mode(struct regulator_dev *rdev, | ||
532 | unsigned int mode) | ||
533 | { | ||
534 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
535 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
536 | u8 power_mode; | ||
537 | int ret; | ||
538 | |||
539 | if (mode == REGULATOR_MODE_NORMAL) | ||
540 | power_mode = (pdata->flags & GLPM_ENABLE) ? | ||
541 | POWER_MODE_GLPM : POWER_MODE_NORMAL; | ||
542 | else if (mode == REGULATOR_MODE_STANDBY) { | ||
543 | /* N-Channel LDOs don't support Low-Power mode. */ | ||
544 | power_mode = (reg->type != REGULATOR_TYPE_LDO_N) ? | ||
545 | POWER_MODE_LPM : POWER_MODE_NORMAL; | ||
546 | } else | ||
547 | return -EINVAL; | ||
548 | |||
549 | ret = max77663_regulator_set_power_mode(reg, power_mode); | ||
550 | if (!ret) | ||
551 | reg->regulator_mode = mode; | ||
552 | |||
553 | return ret; | ||
554 | } | ||
555 | |||
556 | static unsigned int max77663_regulator_get_mode(struct regulator_dev *rdev) | ||
557 | { | ||
558 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
559 | |||
560 | return reg->regulator_mode; | ||
561 | } | ||
562 | |||
563 | static struct regulator_ops max77663_ldo_ops = { | ||
564 | .set_voltage = max77663_regulator_set_voltage, | ||
565 | .get_voltage = max77663_regulator_get_voltage, | ||
566 | .enable = max77663_regulator_enable, | ||
567 | .disable = max77663_regulator_disable, | ||
568 | .is_enabled = max77663_regulator_is_enabled, | ||
569 | .set_mode = max77663_regulator_set_mode, | ||
570 | .get_mode = max77663_regulator_get_mode, | ||
571 | }; | ||
572 | |||
573 | static int max77663_regulator_preinit(struct max77663_regulator *reg) | ||
574 | { | ||
575 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
576 | struct device *parent = _to_parent(reg); | ||
577 | int i; | ||
578 | u8 val, mask; | ||
579 | int ret; | ||
580 | |||
581 | /* Update registers */ | ||
582 | for (i = 0; i <= FPS_REG; i++) { | ||
583 | ret = max77663_read(parent, reg->regs[i].addr, | ||
584 | ®->regs[i].val, 1, 0); | ||
585 | if (ret < 0) { | ||
586 | dev_err(reg->dev, | ||
587 | "preinit: Failed to get register 0x%x\n", | ||
588 | reg->regs[i].addr); | ||
589 | return ret; | ||
590 | } | ||
591 | } | ||
592 | |||
593 | /* Update FPS source */ | ||
594 | if (reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE) | ||
595 | reg->fps_src = FPS_SRC_NONE; | ||
596 | else | ||
597 | reg->fps_src = (reg->regs[FPS_REG].val & FPS_SRC_MASK) | ||
598 | >> FPS_SRC_SHIFT; | ||
599 | |||
600 | dev_dbg(reg->dev, "preinit: initial fps_src=%s\n", | ||
601 | fps_src_name(reg->fps_src)); | ||
602 | |||
603 | /* Update power mode */ | ||
604 | max77663_regulator_get_power_mode(reg); | ||
605 | |||
606 | /* Check Chip Identification */ | ||
607 | ret = max77663_read(parent, MAX77663_REG_CID5, &val, 1, 0); | ||
608 | if (ret < 0) { | ||
609 | dev_err(reg->dev, "preinit: Failed to get register 0x%x\n", | ||
610 | MAX77663_REG_CID5); | ||
611 | return ret; | ||
612 | } | ||
613 | |||
614 | /* If metal revision is less than rev.3, | ||
615 | * set safe_down_uV for stable down scaling. */ | ||
616 | if ((reg->type == REGULATOR_TYPE_SD) && | ||
617 | ((val & CID_DIDM_MASK) >> CID_DIDM_SHIFT) <= 2) | ||
618 | reg->safe_down_uV = SD_SAFE_DOWN_UV; | ||
619 | else | ||
620 | reg->safe_down_uV = 0; | ||
621 | |||
622 | /* Set FPS */ | ||
623 | ret = max77663_regulator_set_fps_cfgs(reg, pdata->fps_cfgs, | ||
624 | pdata->num_fps_cfgs); | ||
625 | if (ret < 0) { | ||
626 | dev_err(reg->dev, "preinit: Failed to set FPSCFG\n"); | ||
627 | return ret; | ||
628 | } | ||
629 | |||
630 | /* N-Channel LDOs don't support Low-Power mode. */ | ||
631 | if ((reg->type == REGULATOR_TYPE_LDO_N) && | ||
632 | (pdata->flags & GLPM_ENABLE)) | ||
633 | pdata->flags &= ~GLPM_ENABLE; | ||
634 | |||
635 | /* To prevent power rail turn-off when change FPS source, | ||
636 | * it must set power mode to NORMAL before change FPS source to NONE | ||
637 | * from SRC_0, SRC_1 and SRC_2. */ | ||
638 | if ((reg->fps_src != FPS_SRC_NONE) && (pdata->fps_src == FPS_SRC_NONE) | ||
639 | && (reg->power_mode != POWER_MODE_NORMAL)) { | ||
640 | val = (pdata->flags & GLPM_ENABLE) ? | ||
641 | POWER_MODE_GLPM : POWER_MODE_NORMAL; | ||
642 | ret = max77663_regulator_set_power_mode(reg, val); | ||
643 | if (ret < 0) { | ||
644 | dev_err(reg->dev, "preinit: Failed to " | ||
645 | "set power mode to POWER_MODE_NORMAL\n"); | ||
646 | return ret; | ||
647 | } | ||
648 | } | ||
649 | |||
650 | ret = max77663_regulator_set_fps_src(reg, pdata->fps_src); | ||
651 | if (ret < 0) { | ||
652 | dev_err(reg->dev, "preinit: Failed to set FPSSRC to %d\n", | ||
653 | pdata->fps_src); | ||
654 | return ret; | ||
655 | } | ||
656 | |||
657 | ret = max77663_regulator_set_fps(reg); | ||
658 | if (ret < 0) { | ||
659 | dev_err(reg->dev, "preinit: Failed to set FPS\n"); | ||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | /* Set initial state */ | ||
664 | if (!pdata->init_apply) | ||
665 | goto skip_init_apply; | ||
666 | |||
667 | if (pdata->init_uV >= 0) { | ||
668 | ret = max77663_regulator_do_set_voltage(reg, pdata->init_uV, | ||
669 | pdata->init_uV); | ||
670 | if (ret < 0) { | ||
671 | dev_err(reg->dev, "preinit: Failed to set voltage to " | ||
672 | "%d\n", pdata->init_uV); | ||
673 | return ret; | ||
674 | } | ||
675 | } | ||
676 | |||
677 | if (pdata->init_enable) | ||
678 | val = (pdata->flags & GLPM_ENABLE) ? | ||
679 | POWER_MODE_GLPM : POWER_MODE_NORMAL; | ||
680 | else | ||
681 | val = POWER_MODE_DISABLE; | ||
682 | |||
683 | ret = max77663_regulator_set_power_mode(reg, val); | ||
684 | if (ret < 0) { | ||
685 | dev_err(reg->dev, | ||
686 | "preinit: Failed to set power mode to %d\n", val); | ||
687 | return ret; | ||
688 | } | ||
689 | |||
690 | skip_init_apply: | ||
691 | if (reg->type == REGULATOR_TYPE_SD) { | ||
692 | val = 0; | ||
693 | mask = 0; | ||
694 | |||
695 | if (pdata->flags & SD_SLEW_RATE_MASK) { | ||
696 | mask |= SD_SR_MASK; | ||
697 | if (pdata->flags & SD_SLEW_RATE_SLOWEST) | ||
698 | val |= (SD_SR_13_75 << SD_SR_SHIFT); | ||
699 | else if (pdata->flags & SD_SLEW_RATE_SLOW) | ||
700 | val |= (SD_SR_27_5 << SD_SR_SHIFT); | ||
701 | else if (pdata->flags & SD_SLEW_RATE_FAST) | ||
702 | val |= (SD_SR_55 << SD_SR_SHIFT); | ||
703 | else | ||
704 | val |= (SD_SR_100 << SD_SR_SHIFT); | ||
705 | } | ||
706 | |||
707 | if (pdata->flags & SD_FORCED_PWM_MODE) { | ||
708 | mask |= SD_FPWM_MASK; | ||
709 | val |= SD_FPWM_MASK; | ||
710 | } | ||
711 | |||
712 | if (pdata->flags & SD_FSRADE_DISABLE) { | ||
713 | mask |= SD_FSRADE_MASK; | ||
714 | val |= SD_FSRADE_MASK; | ||
715 | } | ||
716 | |||
717 | ret = max77663_regulator_cache_write(reg, | ||
718 | reg->regs[CFG_REG].addr, mask, val, | ||
719 | ®->regs[CFG_REG].val); | ||
720 | if (ret < 0) { | ||
721 | dev_err(reg->dev, "preinit: " | ||
722 | "Failed to set register 0x%x\n", | ||
723 | reg->regs[CFG_REG].addr); | ||
724 | return ret; | ||
725 | } | ||
726 | |||
727 | if ((reg->id == MAX77663_REGULATOR_ID_SD0) | ||
728 | && (pdata->flags & EN2_CTRL_SD0)) { | ||
729 | val = POWER_MODE_DISABLE; | ||
730 | ret = max77663_regulator_set_power_mode(reg, val); | ||
731 | if (ret < 0) { | ||
732 | dev_err(reg->dev, "preinit: " | ||
733 | "Failed to set power mode to %d for " | ||
734 | "EN2_CTRL_SD0\n", val); | ||
735 | return ret; | ||
736 | } | ||
737 | |||
738 | ret = max77663_regulator_set_fps_src(reg, FPS_SRC_NONE); | ||
739 | if (ret < 0) { | ||
740 | dev_err(reg->dev, "preinit: " | ||
741 | "Failed to set FPSSRC to FPS_SRC_NONE " | ||
742 | "for EN2_CTRL_SD0\n"); | ||
743 | return ret; | ||
744 | } | ||
745 | } | ||
746 | } | ||
747 | |||
748 | if ((reg->id == MAX77663_REGULATOR_ID_LDO4) | ||
749 | && (pdata->flags & LDO4_EN_TRACKING)) { | ||
750 | val = TRACK4_MASK; | ||
751 | ret = max77663_write(parent, MAX77663_REG_LDO_CFG3, &val, 1, 0); | ||
752 | if (ret < 0) { | ||
753 | dev_err(reg->dev, "preinit: " | ||
754 | "Failed to set register 0x%x\n", | ||
755 | MAX77663_REG_LDO_CFG3); | ||
756 | return ret; | ||
757 | } | ||
758 | } | ||
759 | |||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | #define REGULATOR_SD(_id, _volt_mask, _fps_reg, _min_uV, _max_uV, _step_uV) \ | ||
764 | [MAX77663_REGULATOR_ID_##_id] = { \ | ||
765 | .id = MAX77663_REGULATOR_ID_##_id, \ | ||
766 | .type = REGULATOR_TYPE_SD, \ | ||
767 | .volt_mask = _volt_mask##_VOLT_MASK, \ | ||
768 | .regs = { \ | ||
769 | [VOLT_REG] = { \ | ||
770 | .addr = MAX77663_REG_##_id, \ | ||
771 | }, \ | ||
772 | [CFG_REG] = { \ | ||
773 | .addr = MAX77663_REG_##_id##_CFG, \ | ||
774 | }, \ | ||
775 | [FPS_REG] = { \ | ||
776 | .addr = MAX77663_REG_FPS_##_fps_reg, \ | ||
777 | }, \ | ||
778 | }, \ | ||
779 | .min_uV = _min_uV, \ | ||
780 | .max_uV = _max_uV, \ | ||
781 | .step_uV = _step_uV, \ | ||
782 | .regulator_mode = REGULATOR_MODE_NORMAL, \ | ||
783 | .power_mode = POWER_MODE_NORMAL, \ | ||
784 | .power_mode_mask = SD_POWER_MODE_MASK, \ | ||
785 | .power_mode_shift = SD_POWER_MODE_SHIFT, \ | ||
786 | } | ||
787 | |||
788 | #define REGULATOR_LDO(_id, _type, _min_uV, _max_uV, _step_uV) \ | ||
789 | [MAX77663_REGULATOR_ID_##_id] = { \ | ||
790 | .id = MAX77663_REGULATOR_ID_##_id, \ | ||
791 | .type = REGULATOR_TYPE_LDO_##_type, \ | ||
792 | .volt_mask = LDO_VOLT_MASK, \ | ||
793 | .regs = { \ | ||
794 | [VOLT_REG] = { \ | ||
795 | .addr = MAX77663_REG_##_id##_CFG, \ | ||
796 | }, \ | ||
797 | [CFG_REG] = { \ | ||
798 | .addr = MAX77663_REG_##_id##_CFG2, \ | ||
799 | }, \ | ||
800 | [FPS_REG] = { \ | ||
801 | .addr = MAX77663_REG_FPS_##_id, \ | ||
802 | }, \ | ||
803 | }, \ | ||
804 | .min_uV = _min_uV, \ | ||
805 | .max_uV = _max_uV, \ | ||
806 | .step_uV = _step_uV, \ | ||
807 | .regulator_mode = REGULATOR_MODE_NORMAL, \ | ||
808 | .power_mode = POWER_MODE_NORMAL, \ | ||
809 | .power_mode_mask = LDO_POWER_MODE_MASK, \ | ||
810 | .power_mode_shift = LDO_POWER_MODE_SHIFT, \ | ||
811 | } | ||
812 | |||
813 | static struct max77663_regulator max77663_regs[MAX77663_REGULATOR_ID_NR] = { | ||
814 | REGULATOR_SD(SD0, SDX, SD0, 600000, 3387500, 12500), | ||
815 | REGULATOR_SD(DVSSD0, SDX, NONE, 600000, 3387500, 12500), | ||
816 | REGULATOR_SD(SD1, SD1, SD1, 800000, 1587500, 12500), | ||
817 | REGULATOR_SD(DVSSD1, SD1, NONE, 800000, 1587500, 12500), | ||
818 | REGULATOR_SD(SD2, SDX, SD2, 600000, 3387500, 12500), | ||
819 | REGULATOR_SD(SD3, SDX, SD3, 600000, 3387500, 12500), | ||
820 | REGULATOR_SD(SD4, SDX, SD4, 600000, 3387500, 12500), | ||
821 | |||
822 | REGULATOR_LDO(LDO0, N, 800000, 2350000, 25000), | ||
823 | REGULATOR_LDO(LDO1, N, 800000, 2350000, 25000), | ||
824 | REGULATOR_LDO(LDO2, P, 800000, 3950000, 50000), | ||
825 | REGULATOR_LDO(LDO3, P, 800000, 3950000, 50000), | ||
826 | REGULATOR_LDO(LDO4, P, 800000, 1587500, 12500), | ||
827 | REGULATOR_LDO(LDO5, P, 800000, 3950000, 50000), | ||
828 | REGULATOR_LDO(LDO6, P, 800000, 3950000, 50000), | ||
829 | REGULATOR_LDO(LDO7, N, 800000, 3950000, 50000), | ||
830 | REGULATOR_LDO(LDO8, N, 800000, 3950000, 50000), | ||
831 | }; | ||
832 | |||
833 | #define REGULATOR_DESC(_id, _name) \ | ||
834 | [MAX77663_REGULATOR_ID_##_id] = { \ | ||
835 | .name = max77663_rails(_name), \ | ||
836 | .id = MAX77663_REGULATOR_ID_##_id, \ | ||
837 | .ops = &max77663_ldo_ops, \ | ||
838 | .type = REGULATOR_VOLTAGE, \ | ||
839 | .owner = THIS_MODULE, \ | ||
840 | } | ||
841 | |||
842 | static struct regulator_desc max77663_rdesc[MAX77663_REGULATOR_ID_NR] = { | ||
843 | REGULATOR_DESC(SD0, sd0), | ||
844 | REGULATOR_DESC(DVSSD0, dvssd0), | ||
845 | REGULATOR_DESC(SD1, sd1), | ||
846 | REGULATOR_DESC(DVSSD1, dvssd1), | ||
847 | REGULATOR_DESC(SD2, sd2), | ||
848 | REGULATOR_DESC(SD3, sd3), | ||
849 | REGULATOR_DESC(SD4, sd4), | ||
850 | REGULATOR_DESC(LDO0, ldo0), | ||
851 | REGULATOR_DESC(LDO1, ldo1), | ||
852 | REGULATOR_DESC(LDO2, ldo2), | ||
853 | REGULATOR_DESC(LDO3, ldo3), | ||
854 | REGULATOR_DESC(LDO4, ldo4), | ||
855 | REGULATOR_DESC(LDO5, ldo5), | ||
856 | REGULATOR_DESC(LDO6, ldo6), | ||
857 | REGULATOR_DESC(LDO7, ldo7), | ||
858 | REGULATOR_DESC(LDO8, ldo8), | ||
859 | }; | ||
860 | |||
861 | static int max77663_regulator_probe(struct platform_device *pdev) | ||
862 | { | ||
863 | struct regulator_desc *rdesc; | ||
864 | struct max77663_regulator *reg; | ||
865 | int ret = 0; | ||
866 | |||
867 | if ((pdev->id < 0) || (pdev->id >= MAX77663_REGULATOR_ID_NR)) { | ||
868 | dev_err(&pdev->dev, "Invalid device id %d\n", pdev->id); | ||
869 | return -ENODEV; | ||
870 | } | ||
871 | |||
872 | rdesc = &max77663_rdesc[pdev->id]; | ||
873 | reg = &max77663_regs[pdev->id]; | ||
874 | reg->dev = &pdev->dev; | ||
875 | reg->pdata = dev_get_platdata(&pdev->dev); | ||
876 | |||
877 | dev_dbg(&pdev->dev, "probe: name=%s\n", rdesc->name); | ||
878 | |||
879 | ret = max77663_regulator_preinit(reg); | ||
880 | if (ret) { | ||
881 | dev_err(&pdev->dev, "probe: Failed to preinit regulator %s\n", | ||
882 | rdesc->name); | ||
883 | return ret; | ||
884 | } | ||
885 | |||
886 | reg->rdev = regulator_register(rdesc, &pdev->dev, | ||
887 | ®->pdata->init_data, reg); | ||
888 | if (IS_ERR(reg->rdev)) { | ||
889 | dev_err(&pdev->dev, "probe: Failed to register regulator %s\n", | ||
890 | rdesc->name); | ||
891 | return PTR_ERR(reg->rdev); | ||
892 | } | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | static int max77663_regulator_remove(struct platform_device *pdev) | ||
898 | { | ||
899 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
900 | |||
901 | regulator_unregister(rdev); | ||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | static struct platform_driver max77663_regulator_driver = { | ||
906 | .probe = max77663_regulator_probe, | ||
907 | .remove = __devexit_p(max77663_regulator_remove), | ||
908 | .driver = { | ||
909 | .name = "max77663-regulator", | ||
910 | .owner = THIS_MODULE, | ||
911 | }, | ||
912 | }; | ||
913 | |||
914 | static int __init max77663_regulator_init(void) | ||
915 | { | ||
916 | return platform_driver_register(&max77663_regulator_driver); | ||
917 | } | ||
918 | subsys_initcall(max77663_regulator_init); | ||
919 | |||
920 | static void __exit max77663_reg_exit(void) | ||
921 | { | ||
922 | platform_driver_unregister(&max77663_regulator_driver); | ||
923 | } | ||
924 | module_exit(max77663_reg_exit); | ||
925 | |||
926 | MODULE_LICENSE("GPL v2"); | ||
927 | MODULE_DESCRIPTION("max77663 regulator driver"); | ||
928 | MODULE_VERSION("1.0"); | ||