diff options
| -rw-r--r-- | drivers/regulator/core.c | 112 |
1 files changed, 35 insertions, 77 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e225711bb8bc..0e0d8297dc8e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
| @@ -658,23 +658,32 @@ static struct class regulator_class = { | |||
| 658 | 658 | ||
| 659 | /* Calculate the new optimum regulator operating mode based on the new total | 659 | /* Calculate the new optimum regulator operating mode based on the new total |
| 660 | * consumer load. All locks held by caller */ | 660 | * consumer load. All locks held by caller */ |
| 661 | static void drms_uA_update(struct regulator_dev *rdev) | 661 | static int drms_uA_update(struct regulator_dev *rdev) |
| 662 | { | 662 | { |
| 663 | struct regulator *sibling; | 663 | struct regulator *sibling; |
| 664 | int current_uA = 0, output_uV, input_uV, err; | 664 | int current_uA = 0, output_uV, input_uV, err; |
| 665 | unsigned int mode; | 665 | unsigned int mode; |
| 666 | 666 | ||
| 667 | /* | ||
| 668 | * first check to see if we can set modes at all, otherwise just | ||
| 669 | * tell the consumer everything is OK. | ||
| 670 | */ | ||
| 667 | err = regulator_check_drms(rdev); | 671 | err = regulator_check_drms(rdev); |
| 668 | if (err < 0 || !rdev->desc->ops->get_optimum_mode || | 672 | if (err < 0) |
| 669 | (!rdev->desc->ops->get_voltage && | 673 | return 0; |
| 670 | !rdev->desc->ops->get_voltage_sel) || | 674 | |
| 671 | !rdev->desc->ops->set_mode) | 675 | if (!rdev->desc->ops->get_optimum_mode) |
| 672 | return; | 676 | return 0; |
| 677 | |||
| 678 | if (!rdev->desc->ops->set_mode) | ||
| 679 | return -EINVAL; | ||
| 673 | 680 | ||
| 674 | /* get output voltage */ | 681 | /* get output voltage */ |
| 675 | output_uV = _regulator_get_voltage(rdev); | 682 | output_uV = _regulator_get_voltage(rdev); |
| 676 | if (output_uV <= 0) | 683 | if (output_uV <= 0) { |
| 677 | return; | 684 | rdev_err(rdev, "invalid output voltage found\n"); |
| 685 | return -EINVAL; | ||
| 686 | } | ||
| 678 | 687 | ||
| 679 | /* get input voltage */ | 688 | /* get input voltage */ |
| 680 | input_uV = 0; | 689 | input_uV = 0; |
| @@ -682,8 +691,10 @@ static void drms_uA_update(struct regulator_dev *rdev) | |||
| 682 | input_uV = regulator_get_voltage(rdev->supply); | 691 | input_uV = regulator_get_voltage(rdev->supply); |
| 683 | if (input_uV <= 0) | 692 | if (input_uV <= 0) |
| 684 | input_uV = rdev->constraints->input_uV; | 693 | input_uV = rdev->constraints->input_uV; |
| 685 | if (input_uV <= 0) | 694 | if (input_uV <= 0) { |
| 686 | return; | 695 | rdev_err(rdev, "invalid input voltage found\n"); |
| 696 | return -EINVAL; | ||
| 697 | } | ||
| 687 | 698 | ||
| 688 | /* calc total requested load */ | 699 | /* calc total requested load */ |
| 689 | list_for_each_entry(sibling, &rdev->consumer_list, list) | 700 | list_for_each_entry(sibling, &rdev->consumer_list, list) |
| @@ -695,8 +706,17 @@ static void drms_uA_update(struct regulator_dev *rdev) | |||
| 695 | 706 | ||
| 696 | /* check the new mode is allowed */ | 707 | /* check the new mode is allowed */ |
| 697 | err = regulator_mode_constrain(rdev, &mode); | 708 | err = regulator_mode_constrain(rdev, &mode); |
| 698 | if (err == 0) | 709 | if (err < 0) { |
| 699 | rdev->desc->ops->set_mode(rdev, mode); | 710 | rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", |
| 711 | current_uA, input_uV, output_uV); | ||
| 712 | return err; | ||
| 713 | } | ||
| 714 | |||
| 715 | err = rdev->desc->ops->set_mode(rdev, mode); | ||
| 716 | if (err < 0) | ||
| 717 | rdev_err(rdev, "failed to set optimum mode %x\n", mode); | ||
| 718 | |||
| 719 | return err; | ||
| 700 | } | 720 | } |
| 701 | 721 | ||
| 702 | static int suspend_set_state(struct regulator_dev *rdev, | 722 | static int suspend_set_state(struct regulator_dev *rdev, |
| @@ -3024,75 +3044,13 @@ EXPORT_SYMBOL_GPL(regulator_get_mode); | |||
| 3024 | int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | 3044 | int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) |
| 3025 | { | 3045 | { |
| 3026 | struct regulator_dev *rdev = regulator->rdev; | 3046 | struct regulator_dev *rdev = regulator->rdev; |
| 3027 | struct regulator *consumer; | 3047 | int ret; |
| 3028 | int ret, output_uV, input_uV = 0, total_uA_load = 0; | ||
| 3029 | unsigned int mode; | ||
| 3030 | |||
| 3031 | if (rdev->supply) | ||
| 3032 | input_uV = regulator_get_voltage(rdev->supply); | ||
| 3033 | 3048 | ||
| 3034 | mutex_lock(&rdev->mutex); | 3049 | mutex_lock(&rdev->mutex); |
| 3035 | |||
| 3036 | /* | ||
| 3037 | * first check to see if we can set modes at all, otherwise just | ||
| 3038 | * tell the consumer everything is OK. | ||
| 3039 | */ | ||
| 3040 | regulator->uA_load = uA_load; | 3050 | regulator->uA_load = uA_load; |
| 3041 | ret = regulator_check_drms(rdev); | 3051 | ret = drms_uA_update(rdev); |
| 3042 | if (ret < 0) { | ||
| 3043 | ret = 0; | ||
| 3044 | goto out; | ||
| 3045 | } | ||
| 3046 | |||
| 3047 | if (!rdev->desc->ops->get_optimum_mode) | ||
| 3048 | goto out; | ||
| 3049 | |||
| 3050 | /* | ||
| 3051 | * we can actually do this so any errors are indicators of | ||
| 3052 | * potential real failure. | ||
| 3053 | */ | ||
| 3054 | ret = -EINVAL; | ||
| 3055 | |||
| 3056 | if (!rdev->desc->ops->set_mode) | ||
| 3057 | goto out; | ||
| 3058 | |||
| 3059 | /* get output voltage */ | ||
| 3060 | output_uV = _regulator_get_voltage(rdev); | ||
| 3061 | if (output_uV <= 0) { | ||
| 3062 | rdev_err(rdev, "invalid output voltage found\n"); | ||
| 3063 | goto out; | ||
| 3064 | } | ||
| 3065 | |||
| 3066 | /* No supply? Use constraint voltage */ | ||
| 3067 | if (input_uV <= 0) | ||
| 3068 | input_uV = rdev->constraints->input_uV; | ||
| 3069 | if (input_uV <= 0) { | ||
| 3070 | rdev_err(rdev, "invalid input voltage found\n"); | ||
| 3071 | goto out; | ||
| 3072 | } | ||
| 3073 | |||
| 3074 | /* calc total requested load for this regulator */ | ||
| 3075 | list_for_each_entry(consumer, &rdev->consumer_list, list) | ||
| 3076 | total_uA_load += consumer->uA_load; | ||
| 3077 | |||
| 3078 | mode = rdev->desc->ops->get_optimum_mode(rdev, | ||
| 3079 | input_uV, output_uV, | ||
| 3080 | total_uA_load); | ||
| 3081 | ret = regulator_mode_constrain(rdev, &mode); | ||
| 3082 | if (ret < 0) { | ||
| 3083 | rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", | ||
| 3084 | total_uA_load, input_uV, output_uV); | ||
| 3085 | goto out; | ||
| 3086 | } | ||
| 3087 | |||
| 3088 | ret = rdev->desc->ops->set_mode(rdev, mode); | ||
| 3089 | if (ret < 0) { | ||
| 3090 | rdev_err(rdev, "failed to set optimum mode %x\n", mode); | ||
| 3091 | goto out; | ||
| 3092 | } | ||
| 3093 | ret = mode; | ||
| 3094 | out: | ||
| 3095 | mutex_unlock(&rdev->mutex); | 3052 | mutex_unlock(&rdev->mutex); |
| 3053 | |||
| 3096 | return ret; | 3054 | return ret; |
| 3097 | } | 3055 | } |
| 3098 | EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); | 3056 | EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); |
