diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-class-regulator | 21 | ||||
-rw-r--r-- | drivers/regulator/core.c | 85 | ||||
-rw-r--r-- | include/linux/regulator/consumer.h | 8 | ||||
-rw-r--r-- | include/linux/regulator/driver.h | 10 | ||||
-rw-r--r-- | include/linux/regulator/machine.h | 2 |
5 files changed, 126 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-regulator b/Documentation/ABI/testing/sysfs-class-regulator index e091fa873792..bc578bc60628 100644 --- a/Documentation/ABI/testing/sysfs-class-regulator +++ b/Documentation/ABI/testing/sysfs-class-regulator | |||
@@ -349,3 +349,24 @@ Description: | |||
349 | 349 | ||
350 | This will be one of the same strings reported by | 350 | This will be one of the same strings reported by |
351 | the "state" attribute. | 351 | the "state" attribute. |
352 | |||
353 | What: /sys/class/regulator/.../bypass | ||
354 | Date: September 2012 | ||
355 | KernelVersion: 3.7 | ||
356 | Contact: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
357 | Description: | ||
358 | Some regulator directories will contain a field called | ||
359 | bypass. This indicates if the device is in bypass mode. | ||
360 | |||
361 | This will be one of the following strings: | ||
362 | |||
363 | 'enabled' | ||
364 | 'disabled' | ||
365 | 'unknown' | ||
366 | |||
367 | 'enabled' means the regulator is in bypass mode. | ||
368 | |||
369 | 'disabled' means that the regulator is regulating. | ||
370 | |||
371 | 'unknown' means software cannot determine the state, or | ||
372 | the reported state is invalid. | ||
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 48385318175a..64e16053975e 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,59 @@ out: | |||
2674 | EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); | 2699 | EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); |
2675 | 2700 | ||
2676 | /** | 2701 | /** |
2702 | * regulator_allow_bypass - allow the regulator to go into bypass mode | ||
2703 | * | ||
2704 | * @regulator: Regulator to configure | ||
2705 | * @allow: enable or disable bypass mode | ||
2706 | * | ||
2707 | * Allow the regulator to go into bypass mode if all other consumers | ||
2708 | * for the regulator also enable bypass mode and the machine | ||
2709 | * constraints allow this. Bypass mode means that the regulator is | ||
2710 | * simply passing the input directly to the output with no regulation. | ||
2711 | */ | ||
2712 | int regulator_allow_bypass(struct regulator *regulator, bool enable) | ||
2713 | { | ||
2714 | struct regulator_dev *rdev = regulator->rdev; | ||
2715 | int ret = 0; | ||
2716 | |||
2717 | if (!rdev->desc->ops->set_bypass) | ||
2718 | return 0; | ||
2719 | |||
2720 | if (rdev->constraints && | ||
2721 | !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) | ||
2722 | return 0; | ||
2723 | |||
2724 | mutex_lock(&rdev->mutex); | ||
2725 | |||
2726 | if (enable && !regulator->bypass) { | ||
2727 | rdev->bypass_count++; | ||
2728 | |||
2729 | if (rdev->bypass_count == rdev->open_count) { | ||
2730 | ret = rdev->desc->ops->set_bypass(rdev, enable); | ||
2731 | if (ret != 0) | ||
2732 | rdev->bypass_count--; | ||
2733 | } | ||
2734 | |||
2735 | } else if (!enable && regulator->bypass) { | ||
2736 | rdev->bypass_count--; | ||
2737 | |||
2738 | if (rdev->bypass_count != rdev->open_count) { | ||
2739 | ret = rdev->desc->ops->set_bypass(rdev, enable); | ||
2740 | if (ret != 0) | ||
2741 | rdev->bypass_count++; | ||
2742 | } | ||
2743 | } | ||
2744 | |||
2745 | if (ret == 0) | ||
2746 | regulator->bypass = enable; | ||
2747 | |||
2748 | mutex_unlock(&rdev->mutex); | ||
2749 | |||
2750 | return ret; | ||
2751 | } | ||
2752 | EXPORT_SYMBOL_GPL(regulator_allow_bypass); | ||
2753 | |||
2754 | /** | ||
2677 | * regulator_register_notifier - register regulator event notifier | 2755 | * regulator_register_notifier - register regulator event notifier |
2678 | * @regulator: regulator source | 2756 | * @regulator: regulator source |
2679 | * @nb: notifier block | 2757 | * @nb: notifier block |
@@ -3036,6 +3114,11 @@ static int add_regulator_attributes(struct regulator_dev *rdev) | |||
3036 | if (status < 0) | 3114 | if (status < 0) |
3037 | return status; | 3115 | return status; |
3038 | } | 3116 | } |
3117 | if (ops->get_bypass) { | ||
3118 | status = device_create_file(dev, &dev_attr_bypass); | ||
3119 | if (status < 0) | ||
3120 | return status; | ||
3121 | } | ||
3039 | 3122 | ||
3040 | /* some attributes are type-specific */ | 3123 | /* some attributes are type-specific */ |
3041 | if (rdev->desc->type == REGULATOR_CURRENT) { | 3124 | if (rdev->desc->type == REGULATOR_CURRENT) { |
@@ -3124,6 +3207,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) | |||
3124 | &rdev->use_count); | 3207 | &rdev->use_count); |
3125 | debugfs_create_u32("open_count", 0444, rdev->debugfs, | 3208 | debugfs_create_u32("open_count", 0444, rdev->debugfs, |
3126 | &rdev->open_count); | 3209 | &rdev->open_count); |
3210 | debugfs_create_u32("bypass_count", 0444, rdev->debugfs, | ||
3211 | &rdev->bypass_count); | ||
3127 | } | 3212 | } |
3128 | 3213 | ||
3129 | /** | 3214 | /** |
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index da339fd8c755..ea3e35816621 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h | |||
@@ -177,6 +177,8 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode); | |||
177 | unsigned int regulator_get_mode(struct regulator *regulator); | 177 | unsigned int regulator_get_mode(struct regulator *regulator); |
178 | int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); | 178 | int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); |
179 | 179 | ||
180 | int regulator_allow_bypass(struct regulator *regulator, bool allow); | ||
181 | |||
180 | /* regulator notifier block */ | 182 | /* regulator notifier block */ |
181 | int regulator_register_notifier(struct regulator *regulator, | 183 | int regulator_register_notifier(struct regulator *regulator, |
182 | struct notifier_block *nb); | 184 | struct notifier_block *nb); |
@@ -328,6 +330,12 @@ static inline int regulator_set_optimum_mode(struct regulator *regulator, | |||
328 | return REGULATOR_MODE_NORMAL; | 330 | return REGULATOR_MODE_NORMAL; |
329 | } | 331 | } |
330 | 332 | ||
333 | static inline int regulator_allow_bypass(struct regulator *regulator, | ||
334 | bool allow) | ||
335 | { | ||
336 | return 0; | ||
337 | } | ||
338 | |||
331 | static inline int regulator_register_notifier(struct regulator *regulator, | 339 | static inline int regulator_register_notifier(struct regulator *regulator, |
332 | struct notifier_block *nb) | 340 | struct notifier_block *nb) |
333 | { | 341 | { |
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index bac4c871f3bd..c9869cfbf261 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h | |||
@@ -32,6 +32,8 @@ enum regulator_status { | |||
32 | REGULATOR_STATUS_NORMAL, | 32 | REGULATOR_STATUS_NORMAL, |
33 | REGULATOR_STATUS_IDLE, | 33 | REGULATOR_STATUS_IDLE, |
34 | REGULATOR_STATUS_STANDBY, | 34 | REGULATOR_STATUS_STANDBY, |
35 | /* The regulator is enabled but not regulating */ | ||
36 | REGULATOR_STATUS_BYPASS, | ||
35 | /* in case that any other status doesn't apply */ | 37 | /* in case that any other status doesn't apply */ |
36 | REGULATOR_STATUS_UNDEFINED, | 38 | REGULATOR_STATUS_UNDEFINED, |
37 | }; | 39 | }; |
@@ -67,6 +69,9 @@ enum regulator_status { | |||
67 | * @get_optimum_mode: Get the most efficient operating mode for the regulator | 69 | * @get_optimum_mode: Get the most efficient operating mode for the regulator |
68 | * when running with the specified parameters. | 70 | * when running with the specified parameters. |
69 | * | 71 | * |
72 | * @set_bypass: Set the regulator in bypass mode. | ||
73 | * @get_bypass: Get the regulator bypass mode state. | ||
74 | * | ||
70 | * @enable_time: Time taken for the regulator voltage output voltage to | 75 | * @enable_time: Time taken for the regulator voltage output voltage to |
71 | * stabilise after being enabled, in microseconds. | 76 | * stabilise after being enabled, in microseconds. |
72 | * @set_ramp_delay: Set the ramp delay for the regulator. The driver should | 77 | * @set_ramp_delay: Set the ramp delay for the regulator. The driver should |
@@ -133,6 +138,10 @@ struct regulator_ops { | |||
133 | unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV, | 138 | unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV, |
134 | int output_uV, int load_uA); | 139 | int output_uV, int load_uA); |
135 | 140 | ||
141 | /* control and report on bypass mode */ | ||
142 | int (*set_bypass)(struct regulator_dev *dev, bool enable); | ||
143 | int (*get_bypass)(struct regulator_dev *dev, bool *enable); | ||
144 | |||
136 | /* the operations below are for configuration of regulator state when | 145 | /* the operations below are for configuration of regulator state when |
137 | * its parent PMIC enters a global STANDBY/HIBERNATE state */ | 146 | * its parent PMIC enters a global STANDBY/HIBERNATE state */ |
138 | 147 | ||
@@ -253,6 +262,7 @@ struct regulator_dev { | |||
253 | int exclusive; | 262 | int exclusive; |
254 | u32 use_count; | 263 | u32 use_count; |
255 | u32 open_count; | 264 | u32 open_count; |
265 | u32 bypass_count; | ||
256 | 266 | ||
257 | /* lists we belong to */ | 267 | /* lists we belong to */ |
258 | struct list_head list; /* list of all regulators */ | 268 | struct list_head list; /* list of all regulators */ |
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 40dd0a394cfa..36adbc82de6a 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h | |||
@@ -32,6 +32,7 @@ struct regulator; | |||
32 | * board/machine. | 32 | * board/machine. |
33 | * STATUS: Regulator can be enabled and disabled. | 33 | * STATUS: Regulator can be enabled and disabled. |
34 | * DRMS: Dynamic Regulator Mode Switching is enabled for this regulator. | 34 | * DRMS: Dynamic Regulator Mode Switching is enabled for this regulator. |
35 | * BYPASS: Regulator can be put into bypass mode | ||
35 | */ | 36 | */ |
36 | 37 | ||
37 | #define REGULATOR_CHANGE_VOLTAGE 0x1 | 38 | #define REGULATOR_CHANGE_VOLTAGE 0x1 |
@@ -39,6 +40,7 @@ struct regulator; | |||
39 | #define REGULATOR_CHANGE_MODE 0x4 | 40 | #define REGULATOR_CHANGE_MODE 0x4 |
40 | #define REGULATOR_CHANGE_STATUS 0x8 | 41 | #define REGULATOR_CHANGE_STATUS 0x8 |
41 | #define REGULATOR_CHANGE_DRMS 0x10 | 42 | #define REGULATOR_CHANGE_DRMS 0x10 |
43 | #define REGULATOR_CHANGE_BYPASS 0x20 | ||
42 | 44 | ||
43 | /** | 45 | /** |
44 | * struct regulator_state - regulator state during low power system states | 46 | * struct regulator_state - regulator state during low power system states |