From patchwork Thu Sep 6 10:21:01 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Liu X-Patchwork-Id: 1412821 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id F0419DFFCF for ; Thu, 6 Sep 2012 10:26:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756453Ab2IFK0P (ORCPT ); Thu, 6 Sep 2012 06:26:15 -0400 Received: from na3sys009aog131.obsmtp.com ([74.125.149.247]:39421 "EHLO na3sys009aog131.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754541Ab2IFK0O (ORCPT ); Thu, 6 Sep 2012 06:26:14 -0400 Received: from MSI-MTA.marvell.com ([65.219.4.132]) (using TLSv1) by na3sys009aob131.postini.com ([74.125.148.12]) with SMTP ID DSNKUEh6QbUGkQbTc0fpAvQOQX3XRXrs3ojC@postini.com; Thu, 06 Sep 2012 03:26:14 PDT Received: from maili.marvell.com ([10.68.76.210]) by MSI-MTA.marvell.com with Microsoft SMTPSVC(6.0.3790.3959); Thu, 6 Sep 2012 03:23:56 -0700 Received: from localhost.localdomain (unknown [10.38.36.240]) by maili.marvell.com (Postfix) with ESMTP id DD5974E513; Thu, 6 Sep 2012 03:23:55 -0700 (PDT) From: Kevin Liu To: linux-pm@vger.kernel.org, rjw@sisk.pl, broonie@opensource.wolfsonmicro.com Cc: cxie4@marvell.com, hzhuang1@marvell.com, Kevin Liu Subject: [PATCH] regulator: core: update suspend_prepare and suspend_finish Date: Thu, 6 Sep 2012 18:21:01 +0800 Message-Id: <1346926861-534-1-git-send-email-kliu5@marvell.com> X-Mailer: git-send-email 1.7.0.4 X-OriginalArrivalTime: 06 Sep 2012 10:23:56.0961 (UTC) FILETIME=[B9022910:01CD8C19] Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org add status check in suspend_set_state to avoid redundant enable or disable. suspend_finish just restore the status before suspend_prepare to avoid redundant enable. Signed-off-by: Kevin Liu --- drivers/regulator/core.c | 62 +++++++++++++++++-------------------- include/linux/regulator/driver.h | 10 ++++++ 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f092588..eee22b7 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -656,14 +656,14 @@ static int suspend_set_state(struct regulator_dev *rdev, struct regulator_state *rstate) { int ret = 0; + struct regulator_ops *ops = rdev->desc->ops; /* If we have no suspend mode configration don't set anything; * only warn if the driver implements set_suspend_voltage or * set_suspend_mode callback. */ if (!rstate->enabled && !rstate->disabled) { - if (rdev->desc->ops->set_suspend_voltage || - rdev->desc->ops->set_suspend_mode) + if (ops->set_suspend_voltage || ops->set_suspend_mode) rdev_warn(rdev, "No configuration\n"); return 0; } @@ -673,28 +673,35 @@ static int suspend_set_state(struct regulator_dev *rdev, return -EINVAL; } - if (rstate->enabled && rdev->desc->ops->set_suspend_enable) - ret = rdev->desc->ops->set_suspend_enable(rdev); - else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) - ret = rdev->desc->ops->set_suspend_disable(rdev); - else /* OK if set_suspend_enable or set_suspend_disable is NULL */ + if (rstate->enabled && ops->set_suspend_enable) { + ret = ops->set_suspend_enable(rdev); + if (ret < 0) { + rdev_err(rdev, "failed to enabled\n"); + return ret; + } + rdev->suspend_flag = SUSPEND_ENABLED; + } else if (rstate->disabled && ops->set_suspend_disable) { + ret = ops->set_suspend_disable(rdev); + if (ret < 0) { + rdev_err(rdev, "failed to disabled\n"); + return ret; + } + rdev->suspend_flag = SUSPEND_DISABLED; + } else { + /* OK if set_suspend_enable or set_suspend_disable is NULL */ ret = 0; - - if (ret < 0) { - rdev_err(rdev, "failed to enabled/disable\n"); - return ret; } - if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { - ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); + if (ops->set_suspend_voltage && rstate->uV > 0) { + ret = ops->set_suspend_voltage(rdev, rstate->uV); if (ret < 0) { rdev_err(rdev, "failed to set voltage\n"); return ret; } } - if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { - ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); + if (ops->set_suspend_mode && rstate->mode > 0) { + ret = ops->set_suspend_mode(rdev, rstate->mode); if (ret < 0) { rdev_err(rdev, "failed to set mode\n"); return ret; @@ -3390,31 +3397,20 @@ EXPORT_SYMBOL_GPL(regulator_suspend_prepare); int regulator_suspend_finish(void) { struct regulator_dev *rdev; - int ret = 0, error; + int ret = 0; mutex_lock(®ulator_list_mutex); list_for_each_entry(rdev, ®ulator_list, list) { struct regulator_ops *ops = rdev->desc->ops; mutex_lock(&rdev->mutex); - if ((rdev->use_count > 0 || rdev->constraints->always_on) && - ops->enable) { - error = ops->enable(rdev); - if (error) - ret = error; - } else { - if (!has_full_constraints) - goto unlock; - if (!ops->disable) - goto unlock; - if (!_regulator_is_enabled(rdev)) - goto unlock; - - error = ops->disable(rdev); - if (error) - ret = error; + if ((rdev->suspend_flag == SUSPEND_DISABLED) && ops->enable) { + ret = ops->enable(rdev); + } else if ((rdev->suspend_flag == SUSPEND_ENABLED) && + ops->disable) { + ret = ops->disable(rdev); } -unlock: + rdev->suspend_flag = SUSPEND_NONE; mutex_unlock(&rdev->mutex); } mutex_unlock(®ulator_list_mutex); diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index bac4c87..d545417 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -155,6 +155,15 @@ enum regulator_type { REGULATOR_CURRENT, }; +/* + * Regulator can disable, enable or do nothing during suspend + */ +enum regulator_suspend_flag { + SUSPEND_NONE, + SUSPEND_ENABLED, + SUSPEND_DISABLED, +}; + /** * struct regulator_desc - Static regulator descriptor * @@ -253,6 +262,7 @@ struct regulator_dev { int exclusive; u32 use_count; u32 open_count; + enum regulator_suspend_flag suspend_flag; /* lists we belong to */ struct list_head list; /* list of all regulators */