regulator: When constraining modes fall back to higher power modes
PATCH 1/1 regulator: When constraining modes fall back to higher power modes
If a mode requested by a consumer is not allowed by constraints automatically fall back to a higher power mode if possible. This ensures that consumers get at least the output they requested while allowing machine drivers to transparently limit lower power modes if required.
---
I've not actually had a chance to test this but throwing it out there for comment and testing now; someone with an OMAP board can probably test fairly quickly as the OMAP HSMMC driver is using set_mode().
drivers/regulator/core.c | 24 +++++++++++++++--------- 1 files changed, 15 insertions(+), 9 deletions(-)
drivers/regulator/core.c +15 -9
@@ -197,9 +197,9 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, }/* operating mode constraint check */ -static int regulator_check_mode (struct regulator_dev *rdev,int mode) +static int regulator_mode_constrain (struct regulator_dev *rdev,int *mode) { -switch (mode) { +switch (*mode) {case REGULATOR_MODE_FAST :case REGULATOR_MODE_NORMAL :case REGULATOR_MODE_IDLE :
@@ -217,11 +217,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode)rdev_err (rdev,"operation not allowed\n" );return -EPERM ; } -if (!(rdev->constraints->valid_modes_mask & mode)) { -rdev_err (rdev,"invalid mode %x\n" , mode); -return -EINVAL ; + +/* The modes are bitmasks, the most power hungry modes having +* the lowest values. If the requested mode isn't supported +* try higher modes. */ +while (*mode) { +if (rdev->constraints->valid_modes_mask & *mode) +return 0 ; + *mode /=2 ; } -return 0 ; + +return -EINVAL ; }/* dynamic regulator mode switching constraint check */
@@ -612,7 +618,7 @@ static void drms_uA_update(struct regulator_dev *rdev) output_uV, current_uA);/* check the new mode is allowed */ - err =regulator_check_mode (rdev, mode); + err =regulator_mode_constrain (rdev, &mode);if (err ==0 ) rdev->desc->ops->set_mode (rdev, mode); }
@@ -2005,7 +2011,7 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) }/* constraints check */ - ret =regulator_check_mode (rdev, mode); + ret =regulator_mode_constrain (rdev, mode);if (ret <0 ) goto out;
@@ -2116,7 +2122,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) mode = rdev->desc->ops->get_optimum_mode (rdev, input_uV, output_uV, total_uA_load); - ret =regulator_check_mode (rdev, mode); + ret =regulator_mode_constrain (rdev, &mode);if (ret <0 ) {rdev_err (rdev,"failed to get optimum mode @ %d uA %d -> %d uV\n" , total_uA_load, input_uV, output_uV);
Signature · 1 line
1.7.4.1
Quoted 42 lines · Mark Brown
If a mode requested by a consumer is not allowed by constraints automatically fall back to a higher power mode if possible. This ensures that consumers get at least the output they requested while allowing machine drivers to transparently limit lower power modes if required.
Signed-off-by Mark Brown <[email protected]>---
I've not actually had a chance to test this but throwing it out there for comment and testing now; someone with an OMAP board can probably test fairly quickly as the OMAP HSMMC driver is using
set_mode().drivers/regulator/core.c | 24 +++++++++++++++--------- 1 files changed, 15 insertions(+), 9 deletions(-)drivers/regulator/core.c +5
-5@@ -197,9 +197,9 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, }/* operating mode constraint check */ -static int regulator_check_mode (struct regulator_dev *rdev,int mode) +static int regulator_mode_constrain (struct regulator_dev *rdev,int *mode) { -switch (mode) { +switch (*mode) {case REGULATOR_MODE_FAST :case REGULATOR_MODE_NORMAL :case REGULATOR_MODE_IDLE :@@ -217,11 +217,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode)rdev_err (rdev,"operation not allowed\n" );return -EPERM ; } -if (!(rdev->constraints->valid_modes_mask & mode)) { -rdev_err (rdev,"invalid mode %x\n" , mode); -return -EINVAL ; + +/* The modes are bitmasks, the most power hungry modes having +* the lowest values. If the requested mode isn't supported
drivers/regulator/core.c static int regulator_check_mode(struct regulator_dev *rdev, int mode) · line 231
Quoted 10 lines
drivers/regulator/core.c +7
-1+* try higher modes. */ +while (*mode) { +if (rdev->constraints->valid_modes_mask & *mode) +return 0 ; + *mode /=2 ; } -return 0 ; + +return -EINVAL ; }
It's late and I'm wondering if it's cleaner here just to :-
if (mask & *mode)
return 0;
*mode = fls(mask);
if (*mode)
return 0;
return -EINVAL;
What do you think ?
Liam
Quoted 8 lines · Liam Girdwood
It's late and I'm wondering if it's cleaner here just to :-
if (mask & *mode)
return 0;*mode = fls(mask);
if (*mode)return 0;
This will end up selecting the highest mode in mask, even if it's lower than the one asked for, you'd need to recheck against the original mask. There's a few ways I can think of to do that but they're none of them exceptionally pretty.
Liam Girdwood
AppliedQuoted 8 lines · Mark Brown
If a mode requested by a consumer is not allowed by constraints automatically fall back to a higher power mode if possible. This ensures that consumers get at least the output they requested while allowing machine drivers to transparently limit lower power modes if required.
Signed-off-by Mark Brown <[email protected]>---
Applied.
Thanks
Liam