diff options
author | Lee Jones <lee.jones@linaro.org> | 2013-04-02 08:24:12 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-02 18:01:43 -0400 |
commit | 3fe52289105823867226355e8e957119af50e3a1 (patch) | |
tree | 04b2695466351dde5e2689c156988ee686810029 /drivers/regulator/ab8500.c | |
parent | d7607baf32160a64a2610552868d348b6644b5ef (diff) |
regulator: ab8500: Add mode operation for v-amic
v-amic1 and v-amic2 regulators have dedicated mode registers
and share the same mode bit. This patch adds special handling
for those regulators.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator/ab8500.c')
-rw-r--r-- | drivers/regulator/ab8500.c | 193 |
1 files changed, 161 insertions, 32 deletions
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 6dae5dfb9fde..ac89439a4f9a 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c | |||
@@ -30,10 +30,22 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | 31 | ||
32 | /** | 32 | /** |
33 | * struct ab8500_shared_mode - is used when mode is shared between | ||
34 | * two regulators. | ||
35 | * @shared_regulator: pointer to the other sharing regulator | ||
36 | * @lp_mode_req: low power mode requested by this regulator | ||
37 | */ | ||
38 | struct ab8500_shared_mode { | ||
39 | struct ab8500_regulator_info *shared_regulator; | ||
40 | bool lp_mode_req; | ||
41 | }; | ||
42 | |||
43 | /** | ||
33 | * struct ab8500_regulator_info - ab8500 regulator information | 44 | * struct ab8500_regulator_info - ab8500 regulator information |
34 | * @dev: device pointer | 45 | * @dev: device pointer |
35 | * @desc: regulator description | 46 | * @desc: regulator description |
36 | * @regulator_dev: regulator device | 47 | * @regulator_dev: regulator device |
48 | * @shared_mode: used when mode is shared between two regulators | ||
37 | * @is_enabled: status of regulator (on/off) | 49 | * @is_enabled: status of regulator (on/off) |
38 | * @load_lp_uA: maximum load in idle (low power) mode | 50 | * @load_lp_uA: maximum load in idle (low power) mode |
39 | * @update_bank: bank to control on/off | 51 | * @update_bank: bank to control on/off |
@@ -42,6 +54,11 @@ | |||
42 | * @update_val: bits holding the regulator current mode | 54 | * @update_val: bits holding the regulator current mode |
43 | * @update_val_idle: bits to enable the regulator in idle (low power) mode | 55 | * @update_val_idle: bits to enable the regulator in idle (low power) mode |
44 | * @update_val_normal: bits to enable the regulator in normal (high power) mode | 56 | * @update_val_normal: bits to enable the regulator in normal (high power) mode |
57 | * @mode_bank: bank with location of mode register | ||
58 | * @mode_reg: mode register | ||
59 | * @mode_mask: mask for setting mode | ||
60 | * @mode_val_idle: mode setting for low power | ||
61 | * @mode_val_normal: mode setting for normal power | ||
45 | * @voltage_bank: bank to control regulator voltage | 62 | * @voltage_bank: bank to control regulator voltage |
46 | * @voltage_reg: register to control regulator voltage | 63 | * @voltage_reg: register to control regulator voltage |
47 | * @voltage_mask: mask to control regulator voltage | 64 | * @voltage_mask: mask to control regulator voltage |
@@ -51,6 +68,7 @@ struct ab8500_regulator_info { | |||
51 | struct device *dev; | 68 | struct device *dev; |
52 | struct regulator_desc desc; | 69 | struct regulator_desc desc; |
53 | struct regulator_dev *regulator; | 70 | struct regulator_dev *regulator; |
71 | struct ab8500_shared_mode *shared_mode; | ||
54 | bool is_enabled; | 72 | bool is_enabled; |
55 | int load_lp_uA; | 73 | int load_lp_uA; |
56 | u8 update_bank; | 74 | u8 update_bank; |
@@ -59,6 +77,11 @@ struct ab8500_regulator_info { | |||
59 | u8 update_val; | 77 | u8 update_val; |
60 | u8 update_val_idle; | 78 | u8 update_val_idle; |
61 | u8 update_val_normal; | 79 | u8 update_val_normal; |
80 | u8 mode_bank; | ||
81 | u8 mode_reg; | ||
82 | u8 mode_mask; | ||
83 | u8 mode_val_idle; | ||
84 | u8 mode_val_normal; | ||
62 | u8 voltage_bank; | 85 | u8 voltage_bank; |
63 | u8 voltage_reg; | 86 | u8 voltage_reg; |
64 | u8 voltage_mask; | 87 | u8 voltage_mask; |
@@ -189,6 +212,10 @@ static const unsigned int ldo_vaudio_voltages[] = { | |||
189 | 2600000, /* Duplicated in Vaudio and IsoUicc Control register. */ | 212 | 2600000, /* Duplicated in Vaudio and IsoUicc Control register. */ |
190 | }; | 213 | }; |
191 | 214 | ||
215 | static DEFINE_MUTEX(shared_mode_mutex); | ||
216 | static struct ab8500_shared_mode ldo_anamic1_shared; | ||
217 | static struct ab8500_shared_mode ldo_anamic2_shared; | ||
218 | |||
192 | static int ab8500_regulator_enable(struct regulator_dev *rdev) | 219 | static int ab8500_regulator_enable(struct regulator_dev *rdev) |
193 | { | 220 | { |
194 | int ret; | 221 | int ret; |
@@ -271,8 +298,12 @@ static unsigned int ab8500_regulator_get_optimum_mode( | |||
271 | static int ab8500_regulator_set_mode(struct regulator_dev *rdev, | 298 | static int ab8500_regulator_set_mode(struct regulator_dev *rdev, |
272 | unsigned int mode) | 299 | unsigned int mode) |
273 | { | 300 | { |
274 | int ret; | 301 | int ret = 0; |
275 | u8 update_val; | 302 | u8 bank; |
303 | u8 reg; | ||
304 | u8 mask; | ||
305 | u8 val; | ||
306 | bool dmr = false; /* Dedicated mode register */ | ||
276 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 307 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
277 | 308 | ||
278 | if (info == NULL) { | 309 | if (info == NULL) { |
@@ -280,59 +311,128 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, | |||
280 | return -EINVAL; | 311 | return -EINVAL; |
281 | } | 312 | } |
282 | 313 | ||
283 | switch (mode) { | 314 | if (info->shared_mode) { |
284 | case REGULATOR_MODE_NORMAL: | 315 | /* |
285 | update_val = info->update_val_normal; | 316 | * Special case where mode is shared between two regulators. |
286 | break; | 317 | */ |
287 | case REGULATOR_MODE_IDLE: | 318 | struct ab8500_shared_mode *sm = info->shared_mode; |
288 | update_val = info->update_val_idle; | 319 | mutex_lock(&shared_mode_mutex); |
289 | break; | 320 | |
290 | default: | 321 | if (mode == REGULATOR_MODE_IDLE) { |
291 | return -EINVAL; | 322 | sm->lp_mode_req = true; /* Low power mode requested */ |
323 | if (!((sm->shared_regulator)-> | ||
324 | shared_mode->lp_mode_req)) { | ||
325 | mutex_unlock(&shared_mode_mutex); | ||
326 | return 0; /* Other regulator prevent LP mode */ | ||
327 | } | ||
328 | } else { | ||
329 | sm->lp_mode_req = false; | ||
330 | } | ||
292 | } | 331 | } |
293 | 332 | ||
294 | /* ab8500 regulators share mode and enable in the same register bits. | 333 | if (info->mode_mask) { |
295 | off = 0b00 | 334 | /* Dedicated register for handling mode */ |
296 | low power mode= 0b11 | 335 | |
297 | full powermode = 0b01 | 336 | dmr = true; |
298 | (HW control mode = 0b10) | 337 | |
299 | Thus we don't write to the register when regulator is disabled. | 338 | switch (mode) { |
300 | */ | 339 | case REGULATOR_MODE_NORMAL: |
301 | if (info->is_enabled) { | 340 | val = info->mode_val_normal; |
341 | break; | ||
342 | case REGULATOR_MODE_IDLE: | ||
343 | val = info->mode_val_idle; | ||
344 | break; | ||
345 | default: | ||
346 | if (info->shared_mode) | ||
347 | mutex_unlock(&shared_mode_mutex); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | |||
351 | bank = info->mode_bank; | ||
352 | reg = info->mode_reg; | ||
353 | mask = info->mode_mask; | ||
354 | } else { | ||
355 | /* Mode register same as enable register */ | ||
356 | |||
357 | switch (mode) { | ||
358 | case REGULATOR_MODE_NORMAL: | ||
359 | info->update_val = info->update_val_normal; | ||
360 | val = info->update_val_normal; | ||
361 | break; | ||
362 | case REGULATOR_MODE_IDLE: | ||
363 | info->update_val = info->update_val_idle; | ||
364 | val = info->update_val_idle; | ||
365 | break; | ||
366 | default: | ||
367 | if (info->shared_mode) | ||
368 | mutex_unlock(&shared_mode_mutex); | ||
369 | return -EINVAL; | ||
370 | } | ||
371 | |||
372 | bank = info->update_bank; | ||
373 | reg = info->update_reg; | ||
374 | mask = info->update_mask; | ||
375 | } | ||
376 | |||
377 | if (info->is_enabled || dmr) { | ||
302 | ret = abx500_mask_and_set_register_interruptible(info->dev, | 378 | ret = abx500_mask_and_set_register_interruptible(info->dev, |
303 | info->update_bank, info->update_reg, | 379 | bank, reg, mask, val); |
304 | info->update_mask, update_val); | 380 | if (ret < 0) |
305 | if (ret < 0) { | ||
306 | dev_err(rdev_get_dev(rdev), | 381 | dev_err(rdev_get_dev(rdev), |
307 | "couldn't set regulator mode\n"); | 382 | "couldn't set regulator mode\n"); |
308 | return ret; | ||
309 | } | ||
310 | 383 | ||
311 | dev_vdbg(rdev_get_dev(rdev), | 384 | dev_vdbg(rdev_get_dev(rdev), |
312 | "%s-set_mode (bank, reg, mask, value): " | 385 | "%s-set_mode (bank, reg, mask, value): " |
313 | "0x%x, 0x%x, 0x%x, 0x%x\n", | 386 | "0x%x, 0x%x, 0x%x, 0x%x\n", |
314 | info->desc.name, info->update_bank, info->update_reg, | 387 | info->desc.name, bank, reg, |
315 | info->update_mask, update_val); | 388 | mask, val); |
316 | } | 389 | } |
317 | 390 | ||
318 | info->update_val = update_val; | 391 | if (info->shared_mode) |
392 | mutex_unlock(&shared_mode_mutex); | ||
319 | 393 | ||
320 | return 0; | 394 | return ret; |
321 | } | 395 | } |
322 | 396 | ||
323 | static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev) | 397 | static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev) |
324 | { | 398 | { |
325 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 399 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
326 | int ret; | 400 | int ret; |
401 | u8 val; | ||
402 | u8 val_normal; | ||
403 | u8 val_idle; | ||
327 | 404 | ||
328 | if (info == NULL) { | 405 | if (info == NULL) { |
329 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); | 406 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); |
330 | return -EINVAL; | 407 | return -EINVAL; |
331 | } | 408 | } |
332 | 409 | ||
333 | if (info->update_val == info->update_val_normal) | 410 | /* Need special handling for shared mode */ |
411 | if (info->shared_mode) { | ||
412 | if (info->shared_mode->lp_mode_req) | ||
413 | return REGULATOR_MODE_IDLE; | ||
414 | else | ||
415 | return REGULATOR_MODE_NORMAL; | ||
416 | } | ||
417 | |||
418 | if (info->mode_mask) { | ||
419 | /* Dedicated register for handling mode */ | ||
420 | ret = abx500_get_register_interruptible(info->dev, | ||
421 | info->mode_bank, info->mode_reg, &val); | ||
422 | val = val & info->mode_mask; | ||
423 | |||
424 | val_normal = info->mode_val_normal; | ||
425 | val_idle = info->mode_val_idle; | ||
426 | } else { | ||
427 | /* Mode register same as enable register */ | ||
428 | val = info->update_val; | ||
429 | val_normal = info->update_val_normal; | ||
430 | val_idle = info->update_val_idle; | ||
431 | } | ||
432 | |||
433 | if (val == val_normal) | ||
334 | ret = REGULATOR_MODE_NORMAL; | 434 | ret = REGULATOR_MODE_NORMAL; |
335 | else if (info->update_val == info->update_val_idle) | 435 | else if (val == val_idle) |
336 | ret = REGULATOR_MODE_IDLE; | 436 | ret = REGULATOR_MODE_IDLE; |
337 | else | 437 | else |
338 | ret = -EINVAL; | 438 | ret = -EINVAL; |
@@ -585,6 +685,15 @@ static struct regulator_ops ab8500_regulator_ops = { | |||
585 | .list_voltage = regulator_list_voltage_linear, | 685 | .list_voltage = regulator_list_voltage_linear, |
586 | }; | 686 | }; |
587 | 687 | ||
688 | static struct regulator_ops ab8500_regulator_anamic_mode_ops = { | ||
689 | .enable = ab8500_regulator_enable, | ||
690 | .disable = ab8500_regulator_disable, | ||
691 | .is_enabled = ab8500_regulator_is_enabled, | ||
692 | .set_mode = ab8500_regulator_set_mode, | ||
693 | .get_mode = ab8500_regulator_get_mode, | ||
694 | .list_voltage = regulator_list_voltage_table, | ||
695 | }; | ||
696 | |||
588 | /* AB8500 regulator information */ | 697 | /* AB8500 regulator information */ |
589 | static struct ab8500_regulator_info | 698 | static struct ab8500_regulator_info |
590 | ab8500_regulator_info[AB8500_NUM_REGULATORS] = { | 699 | ab8500_regulator_info[AB8500_NUM_REGULATORS] = { |
@@ -1024,32 +1133,44 @@ static struct ab8500_regulator_info | |||
1024 | [AB8505_LDO_ANAMIC1] = { | 1133 | [AB8505_LDO_ANAMIC1] = { |
1025 | .desc = { | 1134 | .desc = { |
1026 | .name = "LDO-ANAMIC1", | 1135 | .name = "LDO-ANAMIC1", |
1027 | .ops = &ab8500_regulator_ops, | 1136 | .ops = &ab8500_regulator_anamic_mode_ops, |
1028 | .type = REGULATOR_VOLTAGE, | 1137 | .type = REGULATOR_VOLTAGE, |
1029 | .id = AB8505_LDO_ANAMIC1, | 1138 | .id = AB8505_LDO_ANAMIC1, |
1030 | .owner = THIS_MODULE, | 1139 | .owner = THIS_MODULE, |
1031 | .n_voltages = 1, | 1140 | .n_voltages = 1, |
1032 | .volt_table = fixed_2050000_voltage, | 1141 | .volt_table = fixed_2050000_voltage, |
1033 | }, | 1142 | }, |
1143 | .shared_mode = &ldo_anamic1_shared, | ||
1034 | .update_bank = 0x03, | 1144 | .update_bank = 0x03, |
1035 | .update_reg = 0x83, | 1145 | .update_reg = 0x83, |
1036 | .update_mask = 0x08, | 1146 | .update_mask = 0x08, |
1037 | .update_val = 0x08, | 1147 | .update_val = 0x08, |
1148 | .mode_bank = 0x01, | ||
1149 | .mode_reg = 0x54, | ||
1150 | .mode_mask = 0x04, | ||
1151 | .mode_val_idle = 0x04, | ||
1152 | .mode_val_normal = 0x00, | ||
1038 | }, | 1153 | }, |
1039 | [AB8505_LDO_ANAMIC2] = { | 1154 | [AB8505_LDO_ANAMIC2] = { |
1040 | .desc = { | 1155 | .desc = { |
1041 | .name = "LDO-ANAMIC2", | 1156 | .name = "LDO-ANAMIC2", |
1042 | .ops = &ab8500_regulator_ops, | 1157 | .ops = &ab8500_regulator_anamic_mode_ops, |
1043 | .type = REGULATOR_VOLTAGE, | 1158 | .type = REGULATOR_VOLTAGE, |
1044 | .id = AB8505_LDO_ANAMIC2, | 1159 | .id = AB8505_LDO_ANAMIC2, |
1045 | .owner = THIS_MODULE, | 1160 | .owner = THIS_MODULE, |
1046 | .n_voltages = 1, | 1161 | .n_voltages = 1, |
1047 | .volt_table = fixed_2050000_voltage, | 1162 | .volt_table = fixed_2050000_voltage, |
1048 | }, | 1163 | }, |
1164 | .shared_mode = &ldo_anamic2_shared, | ||
1049 | .update_bank = 0x03, | 1165 | .update_bank = 0x03, |
1050 | .update_reg = 0x83, | 1166 | .update_reg = 0x83, |
1051 | .update_mask = 0x10, | 1167 | .update_mask = 0x10, |
1052 | .update_val = 0x10, | 1168 | .update_val = 0x10, |
1169 | .mode_bank = 0x01, | ||
1170 | .mode_reg = 0x54, | ||
1171 | .mode_mask = 0x04, | ||
1172 | .mode_val_idle = 0x04, | ||
1173 | .mode_val_normal = 0x00, | ||
1053 | }, | 1174 | }, |
1054 | [AB8505_LDO_AUX8] = { | 1175 | [AB8505_LDO_AUX8] = { |
1055 | .desc = { | 1176 | .desc = { |
@@ -1589,6 +1710,14 @@ static struct ab8500_regulator_info | |||
1589 | }, | 1710 | }, |
1590 | }; | 1711 | }; |
1591 | 1712 | ||
1713 | static struct ab8500_shared_mode ldo_anamic1_shared = { | ||
1714 | .shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC2], | ||
1715 | }; | ||
1716 | |||
1717 | static struct ab8500_shared_mode ldo_anamic2_shared = { | ||
1718 | .shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC1], | ||
1719 | }; | ||
1720 | |||
1592 | struct ab8500_reg_init { | 1721 | struct ab8500_reg_init { |
1593 | u8 bank; | 1722 | u8 bank; |
1594 | u8 addr; | 1723 | u8 addr; |