diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/arizona-ldo1.c | 4 | ||||
-rw-r--r-- | drivers/regulator/arizona-micsupp.c | 5 | ||||
-rw-r--r-- | drivers/regulator/core.c | 126 | ||||
-rw-r--r-- | drivers/regulator/wm831x-ldo.c | 8 |
4 files changed, 143 insertions, 0 deletions
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index c8f95c07adb6..80e012f14160 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c | |||
@@ -39,6 +39,8 @@ static struct regulator_ops arizona_ldo1_ops = { | |||
39 | .map_voltage = regulator_map_voltage_linear, | 39 | .map_voltage = regulator_map_voltage_linear, |
40 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 40 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
41 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 41 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
42 | .get_bypass = regulator_get_bypass_regmap, | ||
43 | .set_bypass = regulator_set_bypass_regmap, | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | static const struct regulator_desc arizona_ldo1 = { | 46 | static const struct regulator_desc arizona_ldo1 = { |
@@ -49,6 +51,8 @@ static const struct regulator_desc arizona_ldo1 = { | |||
49 | 51 | ||
50 | .vsel_reg = ARIZONA_LDO1_CONTROL_1, | 52 | .vsel_reg = ARIZONA_LDO1_CONTROL_1, |
51 | .vsel_mask = ARIZONA_LDO1_VSEL_MASK, | 53 | .vsel_mask = ARIZONA_LDO1_VSEL_MASK, |
54 | .bypass_reg = ARIZONA_LDO1_CONTROL_1, | ||
55 | .bypass_mask = ARIZONA_LDO1_BYPASS, | ||
52 | .min_uV = 900000, | 56 | .min_uV = 900000, |
53 | .uV_step = 50000, | 57 | .uV_step = 50000, |
54 | .n_voltages = 7, | 58 | .n_voltages = 7, |
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 450a069aa9b6..d9b1f82cc5bd 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c | |||
@@ -82,6 +82,9 @@ static struct regulator_ops arizona_micsupp_ops = { | |||
82 | 82 | ||
83 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 83 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
84 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 84 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
85 | |||
86 | .get_bypass = regulator_get_bypass_regmap, | ||
87 | .set_bypass = regulator_set_bypass_regmap, | ||
85 | }; | 88 | }; |
86 | 89 | ||
87 | static const struct regulator_desc arizona_micsupp = { | 90 | static const struct regulator_desc arizona_micsupp = { |
@@ -95,6 +98,8 @@ static const struct regulator_desc arizona_micsupp = { | |||
95 | .vsel_mask = ARIZONA_LDO2_VSEL_MASK, | 98 | .vsel_mask = ARIZONA_LDO2_VSEL_MASK, |
96 | .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, | 99 | .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, |
97 | .enable_mask = ARIZONA_CPMIC_ENA, | 100 | .enable_mask = ARIZONA_CPMIC_ENA, |
101 | .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, | ||
102 | .bypass_mask = ARIZONA_CPMIC_BYPASS, | ||
98 | 103 | ||
99 | .owner = THIS_MODULE, | 104 | .owner = THIS_MODULE, |
100 | }; | 105 | }; |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 48385318175a..419805cdd9d7 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -77,6 +77,7 @@ struct regulator { | |||
77 | struct device *dev; | 77 | struct device *dev; |
78 | struct list_head list; | 78 | struct list_head list; |
79 | unsigned int always_on:1; | 79 | unsigned int always_on:1; |
80 | unsigned int bypass:1; | ||
80 | int uA_load; | 81 | int uA_load; |
81 | int min_uV; | 82 | int min_uV; |
82 | int max_uV; | 83 | int max_uV; |
@@ -394,6 +395,9 @@ static ssize_t regulator_status_show(struct device *dev, | |||
394 | case REGULATOR_STATUS_STANDBY: | 395 | case REGULATOR_STATUS_STANDBY: |
395 | label = "standby"; | 396 | label = "standby"; |
396 | break; | 397 | break; |
398 | case REGULATOR_STATUS_BYPASS: | ||
399 | label = "bypass"; | ||
400 | break; | ||
397 | case REGULATOR_STATUS_UNDEFINED: | 401 | case REGULATOR_STATUS_UNDEFINED: |
398 | label = "undefined"; | 402 | label = "undefined"; |
399 | break; | 403 | break; |
@@ -585,6 +589,27 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev, | |||
585 | static DEVICE_ATTR(suspend_standby_state, 0444, | 589 | static DEVICE_ATTR(suspend_standby_state, 0444, |
586 | regulator_suspend_standby_state_show, NULL); | 590 | regulator_suspend_standby_state_show, NULL); |
587 | 591 | ||
592 | static ssize_t regulator_bypass_show(struct device *dev, | ||
593 | struct device_attribute *attr, char *buf) | ||
594 | { | ||
595 | struct regulator_dev *rdev = dev_get_drvdata(dev); | ||
596 | const char *report; | ||
597 | bool bypass; | ||
598 | int ret; | ||
599 | |||
600 | ret = rdev->desc->ops->get_bypass(rdev, &bypass); | ||
601 | |||
602 | if (ret != 0) | ||
603 | report = "unknown"; | ||
604 | else if (bypass) | ||
605 | report = "enabled"; | ||
606 | else | ||
607 | report = "disabled"; | ||
608 | |||
609 | return sprintf(buf, "%s\n", report); | ||
610 | } | ||
611 | static DEVICE_ATTR(bypass, 0444, | ||
612 | regulator_bypass_show, NULL); | ||
588 | 613 | ||
589 | /* | 614 | /* |
590 | * These are the only attributes are present for all regulators. | 615 | * These are the only attributes are present for all regulators. |
@@ -2674,6 +2699,100 @@ out: | |||
2674 | EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); | 2699 | EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); |
2675 | 2700 | ||
2676 | /** | 2701 | /** |
2702 | * regulator_set_bypass_regmap - Default set_bypass() using regmap | ||
2703 | * | ||
2704 | * @rdev: device to operate on. | ||
2705 | * @enable: state to set. | ||
2706 | */ | ||
2707 | int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) | ||
2708 | { | ||
2709 | unsigned int val; | ||
2710 | |||
2711 | if (enable) | ||
2712 | val = rdev->desc->bypass_mask; | ||
2713 | else | ||
2714 | val = 0; | ||
2715 | |||
2716 | return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, | ||
2717 | rdev->desc->bypass_mask, val); | ||
2718 | } | ||
2719 | EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); | ||
2720 | |||
2721 | /** | ||
2722 | * regulator_get_bypass_regmap - Default get_bypass() using regmap | ||
2723 | * | ||
2724 | * @rdev: device to operate on. | ||
2725 | * @enable: current state. | ||
2726 | */ | ||
2727 | int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) | ||
2728 | { | ||
2729 | unsigned int val; | ||
2730 | int ret; | ||
2731 | |||
2732 | ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); | ||
2733 | if (ret != 0) | ||
2734 | return ret; | ||
2735 | |||
2736 | *enable = val & rdev->desc->bypass_mask; | ||
2737 | |||
2738 | return 0; | ||
2739 | } | ||
2740 | EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); | ||
2741 | |||
2742 | /** | ||
2743 | * regulator_allow_bypass - allow the regulator to go into bypass mode | ||
2744 | * | ||
2745 | * @regulator: Regulator to configure | ||
2746 | * @allow: enable or disable bypass mode | ||
2747 | * | ||
2748 | * Allow the regulator to go into bypass mode if all other consumers | ||
2749 | * for the regulator also enable bypass mode and the machine | ||
2750 | * constraints allow this. Bypass mode means that the regulator is | ||
2751 | * simply passing the input directly to the output with no regulation. | ||
2752 | */ | ||
2753 | int regulator_allow_bypass(struct regulator *regulator, bool enable) | ||
2754 | { | ||
2755 | struct regulator_dev *rdev = regulator->rdev; | ||
2756 | int ret = 0; | ||
2757 | |||
2758 | if (!rdev->desc->ops->set_bypass) | ||
2759 | return 0; | ||
2760 | |||
2761 | if (rdev->constraints && | ||
2762 | !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) | ||
2763 | return 0; | ||
2764 | |||
2765 | mutex_lock(&rdev->mutex); | ||
2766 | |||
2767 | if (enable && !regulator->bypass) { | ||
2768 | rdev->bypass_count++; | ||
2769 | |||
2770 | if (rdev->bypass_count == rdev->open_count) { | ||
2771 | ret = rdev->desc->ops->set_bypass(rdev, enable); | ||
2772 | if (ret != 0) | ||
2773 | rdev->bypass_count--; | ||
2774 | } | ||
2775 | |||
2776 | } else if (!enable && regulator->bypass) { | ||
2777 | rdev->bypass_count--; | ||
2778 | |||
2779 | if (rdev->bypass_count != rdev->open_count) { | ||
2780 | ret = rdev->desc->ops->set_bypass(rdev, enable); | ||
2781 | if (ret != 0) | ||
2782 | rdev->bypass_count++; | ||
2783 | } | ||
2784 | } | ||
2785 | |||
2786 | if (ret == 0) | ||
2787 | regulator->bypass = enable; | ||
2788 | |||
2789 | mutex_unlock(&rdev->mutex); | ||
2790 | |||
2791 | return ret; | ||
2792 | } | ||
2793 | EXPORT_SYMBOL_GPL(regulator_allow_bypass); | ||
2794 | |||
2795 | /** | ||
2677 | * regulator_register_notifier - register regulator event notifier | 2796 | * regulator_register_notifier - register regulator event notifier |
2678 | * @regulator: regulator source | 2797 | * @regulator: regulator source |
2679 | * @nb: notifier block | 2798 | * @nb: notifier block |
@@ -3036,6 +3155,11 @@ static int add_regulator_attributes(struct regulator_dev *rdev) | |||
3036 | if (status < 0) | 3155 | if (status < 0) |
3037 | return status; | 3156 | return status; |
3038 | } | 3157 | } |
3158 | if (ops->get_bypass) { | ||
3159 | status = device_create_file(dev, &dev_attr_bypass); | ||
3160 | if (status < 0) | ||
3161 | return status; | ||
3162 | } | ||
3039 | 3163 | ||
3040 | /* some attributes are type-specific */ | 3164 | /* some attributes are type-specific */ |
3041 | if (rdev->desc->type == REGULATOR_CURRENT) { | 3165 | if (rdev->desc->type == REGULATOR_CURRENT) { |
@@ -3124,6 +3248,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) | |||
3124 | &rdev->use_count); | 3248 | &rdev->use_count); |
3125 | debugfs_create_u32("open_count", 0444, rdev->debugfs, | 3249 | debugfs_create_u32("open_count", 0444, rdev->debugfs, |
3126 | &rdev->open_count); | 3250 | &rdev->open_count); |
3251 | debugfs_create_u32("bypass_count", 0444, rdev->debugfs, | ||
3252 | &rdev->bypass_count); | ||
3127 | } | 3253 | } |
3128 | 3254 | ||
3129 | /** | 3255 | /** |
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 5cb70ca1e98d..f203a972dedf 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c | |||
@@ -237,6 +237,8 @@ static struct regulator_ops wm831x_gp_ldo_ops = { | |||
237 | .set_mode = wm831x_gp_ldo_set_mode, | 237 | .set_mode = wm831x_gp_ldo_set_mode, |
238 | .get_status = wm831x_gp_ldo_get_status, | 238 | .get_status = wm831x_gp_ldo_get_status, |
239 | .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode, | 239 | .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode, |
240 | .get_bypass = regulator_get_bypass_regmap, | ||
241 | .set_bypass = regulator_set_bypass_regmap, | ||
240 | 242 | ||
241 | .is_enabled = regulator_is_enabled_regmap, | 243 | .is_enabled = regulator_is_enabled_regmap, |
242 | .enable = regulator_enable_regmap, | 244 | .enable = regulator_enable_regmap, |
@@ -293,6 +295,8 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) | |||
293 | ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; | 295 | ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; |
294 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; | 296 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; |
295 | ldo->desc.enable_mask = 1 << id; | 297 | ldo->desc.enable_mask = 1 << id; |
298 | ldo->desc.bypass_reg = ldo->base; | ||
299 | ldo->desc.bypass_mask = WM831X_LDO1_SWI; | ||
296 | 300 | ||
297 | config.dev = pdev->dev.parent; | 301 | config.dev = pdev->dev.parent; |
298 | if (pdata) | 302 | if (pdata) |
@@ -488,6 +492,8 @@ static struct regulator_ops wm831x_aldo_ops = { | |||
488 | .get_mode = wm831x_aldo_get_mode, | 492 | .get_mode = wm831x_aldo_get_mode, |
489 | .set_mode = wm831x_aldo_set_mode, | 493 | .set_mode = wm831x_aldo_set_mode, |
490 | .get_status = wm831x_aldo_get_status, | 494 | .get_status = wm831x_aldo_get_status, |
495 | .set_bypass = regulator_set_bypass_regmap, | ||
496 | .get_bypass = regulator_get_bypass_regmap, | ||
491 | 497 | ||
492 | .is_enabled = regulator_is_enabled_regmap, | 498 | .is_enabled = regulator_is_enabled_regmap, |
493 | .enable = regulator_enable_regmap, | 499 | .enable = regulator_enable_regmap, |
@@ -544,6 +550,8 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) | |||
544 | ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; | 550 | ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; |
545 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; | 551 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; |
546 | ldo->desc.enable_mask = 1 << id; | 552 | ldo->desc.enable_mask = 1 << id; |
553 | ldo->desc.bypass_reg = ldo->base; | ||
554 | ldo->desc.bypass_mask = WM831X_LDO7_SWI; | ||
547 | 555 | ||
548 | config.dev = pdev->dev.parent; | 556 | config.dev = pdev->dev.parent; |
549 | if (pdata) | 557 | if (pdata) |