From patchwork Thu Aug 28 19:36:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 4807841 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CE5BC9F37E for ; Thu, 28 Aug 2014 19:39:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E0FAB200FE for ; Thu, 28 Aug 2014 19:39:57 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id EB8A1200F3 for ; Thu, 28 Aug 2014 19:39:56 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XN5VD-0007oJ-Hp; Thu, 28 Aug 2014 19:36:59 +0000 Received: from mail-pa0-x231.google.com ([2607:f8b0:400e:c03::231]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XN5V6-0007kH-BY for linux-arm-kernel@lists.infradead.org; Thu, 28 Aug 2014 19:36:53 +0000 Received: by mail-pa0-f49.google.com with SMTP id kq14so3782092pab.22 for ; Thu, 28 Aug 2014 12:36:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=p4ZKdxS0PTqDrEckXu4396433SZsLdaEnZcnOh4FozA=; b=iOZxDRM2OEL2QmNiLijahaBI1Jmr1rT73/iYeI1Jo5NKNhwnIsjgp9jnb1v4yjvid6 6gj8FkDRsl6HTGRSFjB4b2sn3PFeB29hxIztU+doTBQnhobccBdl3C2ogJ52sQPOB3Dm p5EaETHELjY7FoRheOsZFsP4V7Mgp5kN62j0U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=p4ZKdxS0PTqDrEckXu4396433SZsLdaEnZcnOh4FozA=; b=Guc5NTt4cZkDB2dUXEYEYRdJWltWq3c3O+DfQicBd2Ji1dhiRWmFHEB3CaAQmJkLGY 4LqqeWVPIkMxR6KFMC0R5Ndu/6P4yTmg1AosMGZ2P27LzQuN+zRzQ1FbrRDsFeZ/2vwl Yb4GbnHJLZlqAS+quYLCFazbxSU7wAlsbfF//CS9iPuQgx/1yqrppj8B6ZKgE7rVWg2s bBfnXomvPmPc20ZzFopK8a7WUjnHj+Go24w7GWLQpjGLEFFv7HpLn6pwPtcKYzKGyi9m X+GolUwRUgURoKd6yBZ00gsjV+doquw5zf/8OfGH/dZEe38bvmK+lNh05uUrxZlzVLId HP8A== X-Gm-Message-State: ALoCoQn5BOZOkpn+4R9/aNUqHWoHHOQhBFryrWz4Ba+ZQb4kZUXbjS+cXtm3BqrDfW2uLPQrlrF5 X-Received: by 10.68.189.137 with SMTP id gi9mr8849406pbc.87.1409254590610; Thu, 28 Aug 2014 12:36:30 -0700 (PDT) Received: from tictac.mtv.corp.google.com (tictac.mtv.corp.google.com [172.22.162.15]) by mx.google.com with ESMTPSA id gf5sm4313884pbc.89.2014.08.28.12.36.29 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 28 Aug 2014 12:36:30 -0700 (PDT) From: Doug Anderson To: Mark Brown , Heiko Stuebner , olof@lixom.net, Arnd Bergmann Subject: [PATCH 1/2] regulator: core: Add REGULATOR_EVENT_PRE_VOLTAGE_CHANGE (and ABORT) Date: Thu, 28 Aug 2014 12:36:04 -0700 Message-Id: <1409254565-10677-2-git-send-email-dianders@chromium.org> X-Mailer: git-send-email 2.1.0.rc2.206.gedb03e5 In-Reply-To: <1409254565-10677-1-git-send-email-dianders@chromium.org> References: <1409254565-10677-1-git-send-email-dianders@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140828_123652_443696_72D9420A X-CRM114-Status: GOOD ( 16.41 ) X-Spam-Score: -0.8 (/) Cc: Addy Ke , lgirdwood@gmail.com, linux-kernel@vger.kernel.org, Doug Anderson , Sonny Rao , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Heiko Stübner In some cases we need to know when a regulator is about to be changed. Add a way for clients to be notified. Note that for set_voltage() we don't necessarily know what voltage we'll end up with, so we tell the client what the range will be so they can prepare. Signed-off-by: Heiko Stübner Signed-off-by: Doug Anderson --- drivers/regulator/core.c | 63 +++++++++++++++++++++++++++++++++----- include/linux/regulator/consumer.h | 20 ++++++++++++ 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7bce715..b31d706 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -102,7 +102,7 @@ static int _regulator_disable(struct regulator_dev *rdev); static int _regulator_get_voltage(struct regulator_dev *rdev); static int _regulator_get_current_limit(struct regulator_dev *rdev); static unsigned int _regulator_get_mode(struct regulator_dev *rdev); -static void _notifier_call_chain(struct regulator_dev *rdev, +static int _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data); static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV); @@ -2406,6 +2406,55 @@ int regulator_is_supported_voltage(struct regulator *regulator, } EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); +static int _regulator_call_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned *selector) +{ + struct pre_voltage_change_data data; + int ret; + + data.old_uV = _regulator_get_voltage(rdev); + data.min_uV = min_uV; + data.max_uV = max_uV; + ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, + &data); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + + ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); + if (ret >= 0) + return ret; + + _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, + (void *)data.old_uV); + + return ret; +} + +static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, + int uV, unsigned selector) +{ + struct pre_voltage_change_data data; + int ret; + + data.old_uV = _regulator_get_voltage(rdev); + data.min_uV = uV; + data.max_uV = uV; + ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, + &data); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + + ret = rdev->desc->ops->set_voltage_sel(rdev, selector); + if (ret >= 0) + return ret; + + _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, + (void *)data.old_uV); + + return ret; +} + static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { @@ -2433,8 +2482,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } if (rdev->desc->ops->set_voltage) { - ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, - &selector); + ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, + &selector); if (ret >= 0) { if (rdev->desc->ops->list_voltage) @@ -2469,8 +2518,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, if (old_selector == selector) ret = 0; else - ret = rdev->desc->ops->set_voltage_sel( - rdev, ret); + ret = _regulator_call_set_voltage_sel( + rdev, best_val, selector); } else { ret = -EINVAL; } @@ -3116,11 +3165,11 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier); /* notify regulator consumers and downstream regulator consumers. * Note mutex must be held by caller. */ -static void _notifier_call_chain(struct regulator_dev *rdev, +static int _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { /* call rdev chain first */ - blocking_notifier_call_chain(&rdev->notifier, event, data); + return blocking_notifier_call_chain(&rdev->notifier, event, data); } /** diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index f8a8733..d347c80 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -93,7 +93,12 @@ struct regmap; * OVER_TEMP Regulator over temp. * FORCE_DISABLE Regulator forcibly shut down by software. * VOLTAGE_CHANGE Regulator voltage changed. + * Data passed is old voltage cast to (void *). * DISABLE Regulator was disabled. + * PRE_VOLTAGE_CHANGE Regulator is about to have voltage changed. + * Data passed is "struct pre_voltage_change_data" + * ABORT_VOLTAGE_CHANGE Regulator voltage change failed for some reason. + * Data passed is old voltage cast to (void *). * * NOTE: These events can be OR'ed together when passed into handler. */ @@ -106,6 +111,21 @@ struct regmap; #define REGULATOR_EVENT_FORCE_DISABLE 0x20 #define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40 #define REGULATOR_EVENT_DISABLE 0x80 +#define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE 0x100 +#define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200 + +/** + * struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event + * + * @old_uV: Current voltage before change. + * @min_uV: Min voltage we'll change to. + * @max_uV: Max voltage we'll change to. + */ +struct pre_voltage_change_data { + unsigned long old_uV; + unsigned long min_uV; + unsigned long max_uV; +}; struct regulator;