diff options
-rw-r--r-- | drivers/regulator/s2mps11.c | 51 | ||||
-rw-r--r-- | include/linux/mfd/samsung/s2mps14.h | 2 |
2 files changed, 52 insertions, 1 deletions
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 65697b1a26c0..cdd8d4066121 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c | |||
@@ -39,6 +39,11 @@ struct s2mps11_info { | |||
39 | int ramp_delay16; | 39 | int ramp_delay16; |
40 | int ramp_delay7810; | 40 | int ramp_delay7810; |
41 | int ramp_delay9; | 41 | int ramp_delay9; |
42 | /* | ||
43 | * One bit for each S2MPS14 regulator whether the suspend mode | ||
44 | * was enabled. | ||
45 | */ | ||
46 | unsigned int s2mps14_suspend_state:30; | ||
42 | }; | 47 | }; |
43 | 48 | ||
44 | static int get_ramp_delay(int ramp_delay) | 49 | static int get_ramp_delay(int ramp_delay) |
@@ -399,15 +404,59 @@ static const struct regulator_desc s2mps11_regulators[] = { | |||
399 | regulator_desc_s2mps11_buck10, | 404 | regulator_desc_s2mps11_buck10, |
400 | }; | 405 | }; |
401 | 406 | ||
407 | static int s2mps14_regulator_enable(struct regulator_dev *rdev) | ||
408 | { | ||
409 | struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); | ||
410 | unsigned int val; | ||
411 | |||
412 | if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) | ||
413 | val = S2MPS14_ENABLE_SUSPEND; | ||
414 | else | ||
415 | val = rdev->desc->enable_mask; | ||
416 | |||
417 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
418 | rdev->desc->enable_mask, val); | ||
419 | } | ||
420 | |||
421 | static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) | ||
422 | { | ||
423 | int ret; | ||
424 | unsigned int val; | ||
425 | struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); | ||
426 | |||
427 | /* LDO3 should be always on and does not support suspend mode */ | ||
428 | if (rdev_get_id(rdev) == S2MPS14_LDO3) | ||
429 | return 0; | ||
430 | |||
431 | ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); | ||
432 | if (ret < 0) | ||
433 | return ret; | ||
434 | |||
435 | s2mps11->s2mps14_suspend_state |= (1 << rdev_get_id(rdev)); | ||
436 | /* | ||
437 | * Don't enable suspend mode if regulator is already disabled because | ||
438 | * this would effectively for a short time turn on the regulator after | ||
439 | * resuming. | ||
440 | * However we still want to toggle the suspend_state bit for regulator | ||
441 | * in case if it got enabled before suspending the system. | ||
442 | */ | ||
443 | if (!(val & rdev->desc->enable_mask)) | ||
444 | return 0; | ||
445 | |||
446 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
447 | rdev->desc->enable_mask, S2MPS14_ENABLE_SUSPEND); | ||
448 | } | ||
449 | |||
402 | static struct regulator_ops s2mps14_reg_ops = { | 450 | static struct regulator_ops s2mps14_reg_ops = { |
403 | .list_voltage = regulator_list_voltage_linear, | 451 | .list_voltage = regulator_list_voltage_linear, |
404 | .map_voltage = regulator_map_voltage_linear, | 452 | .map_voltage = regulator_map_voltage_linear, |
405 | .is_enabled = regulator_is_enabled_regmap, | 453 | .is_enabled = regulator_is_enabled_regmap, |
406 | .enable = regulator_enable_regmap, | 454 | .enable = s2mps14_regulator_enable, |
407 | .disable = regulator_disable_regmap, | 455 | .disable = regulator_disable_regmap, |
408 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 456 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
409 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 457 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
410 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | 458 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
459 | .set_suspend_disable = s2mps14_regulator_set_suspend_disable, | ||
411 | }; | 460 | }; |
412 | 461 | ||
413 | #define regulator_desc_s2mps14_ldo1(num) { \ | 462 | #define regulator_desc_s2mps14_ldo1(num) { \ |
diff --git a/include/linux/mfd/samsung/s2mps14.h b/include/linux/mfd/samsung/s2mps14.h index ec1e0857ddde..4b449b8ac548 100644 --- a/include/linux/mfd/samsung/s2mps14.h +++ b/include/linux/mfd/samsung/s2mps14.h | |||
@@ -146,6 +146,8 @@ enum s2mps14_regulators { | |||
146 | #define S2MPS14_BUCK_VSEL_MASK 0xFF | 146 | #define S2MPS14_BUCK_VSEL_MASK 0xFF |
147 | #define S2MPS14_ENABLE_MASK (0x03 << S2MPS14_ENABLE_SHIFT) | 147 | #define S2MPS14_ENABLE_MASK (0x03 << S2MPS14_ENABLE_SHIFT) |
148 | #define S2MPS14_ENABLE_SHIFT 6 | 148 | #define S2MPS14_ENABLE_SHIFT 6 |
149 | /* On/Off controlled by PWREN */ | ||
150 | #define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT) | ||
149 | #define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1) | 151 | #define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1) |
150 | #define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) | 152 | #define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) |
151 | 153 | ||