From 4e013b64c1ee3a60438caa0df6bf79664e0272bc Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Wed, 31 Aug 2016 11:11:18 +0800 Subject: [PATCH] greybus: power_supply: Add runtime pm support Modify Power_supply greybus driver to support runtime PM framework. During charging state, the driver will block remote device of suspending, and then enables runtime suspend when remote device is in none chargin state. Testing Done: Compiled and verified on EVT2, EVT2 1x2 GPB test module and Device class daughter board. Signed-off-by: Philip Yang Reviewed-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/power_supply.c | 62 ++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 578d38b25d71..68dd3d2f7585 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -50,6 +50,8 @@ struct gb_power_supply { bool changed; struct gb_power_supply_prop *props; enum power_supply_property *props_raw; + bool pm_acquired; + struct mutex supply_lock; }; struct gb_power_supplies { @@ -75,10 +77,13 @@ struct gb_power_supply_changes { struct gb_power_supply_prop *prop); }; +static void gb_power_supply_state_change(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop); + static const struct gb_power_supply_changes psy_props_changes[] = { { .prop = GB_POWER_SUPPLY_PROP_STATUS, .tolerance_change = 0, - .prop_changed = NULL, + .prop_changed = gb_power_supply_state_change, }, { .prop = GB_POWER_SUPPLY_PROP_TEMP, .tolerance_change = 500, @@ -349,6 +354,40 @@ static void __gb_power_supply_changed(struct gb_power_supply *gbpsy) } #endif +static void gb_power_supply_state_change(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + int ret; + + /* + * Check gbpsy->pm_acquired to make sure only one pair of 'get_sync' + * and 'put_autosuspend' runtime pm call for state property change. + */ + mutex_lock(&gbpsy->supply_lock); + + if ((prop->val == GB_POWER_SUPPLY_STATUS_CHARGING) && + !gbpsy->pm_acquired) { + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + dev_err(&connection->bundle->dev, + "Fail to set wake lock for charging state\n"); + else + gbpsy->pm_acquired = true; + } else { + if (gbpsy->pm_acquired) { + ret = gb_pm_runtime_put_autosuspend(connection->bundle); + if (ret) + dev_err(&connection->bundle->dev, + "Fail to set wake unlock for none charging\n"); + else + gbpsy->pm_acquired = false; + } + } + + mutex_unlock(&gbpsy->supply_lock); +} + static void check_changed(struct gb_power_supply *gbpsy, struct gb_power_supply_prop *prop) { @@ -655,12 +694,17 @@ static int is_cache_valid(struct gb_power_supply *gbpsy) static int gb_power_supply_status_get(struct gb_power_supply *gbpsy) { + struct gb_connection *connection = get_conn_from_psy(gbpsy); int ret = 0; int i; if (is_cache_valid(gbpsy)) return 0; + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + return ret; + for (i = 0; i < gbpsy->properties_count; i++) { ret = __gb_power_supply_property_update(gbpsy, gbpsy->props[i].prop); @@ -671,6 +715,7 @@ static int gb_power_supply_status_get(struct gb_power_supply *gbpsy) if (ret == 0) gbpsy->last_update = jiffies; + gb_pm_runtime_put_autosuspend(connection->bundle); return ret; } @@ -725,9 +770,16 @@ static int gb_power_supply_property_set(struct gb_power_supply *gbpsy, struct gb_power_supply_set_property_request req; int ret; + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + return ret; + prop = get_psy_prop(gbpsy, psp); - if (!prop) - return -EINVAL; + if (!prop) { + ret = -EINVAL; + goto out; + } + req.psy_id = gbpsy->id; req.property = prop->gb_prop; req.prop_val = cpu_to_le32((s32)val); @@ -741,6 +793,7 @@ static int gb_power_supply_property_set(struct gb_power_supply *gbpsy, prop->val = val; out: + gb_pm_runtime_put_autosuspend(connection->bundle); return ret; } @@ -883,6 +936,8 @@ static int gb_power_supply_enable(struct gb_power_supply *gbpsy) if (ret < 0) return ret; + mutex_init(&gbpsy->supply_lock); + ret = gb_power_supply_register(gbpsy); if (ret < 0) return ret; @@ -1067,6 +1122,7 @@ static int gb_power_supply_probe(struct gb_bundle *bundle, if (ret < 0) goto error_connection_disable; + gb_pm_runtime_put_autosuspend(bundle); return 0; error_connection_disable: