From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753198AbdBCXR0 (ORCPT ); Fri, 3 Feb 2017 18:17:26 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:36098 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752932AbdBCXQp (ORCPT ); Fri, 3 Feb 2017 18:16:45 -0500 From: Dmitry Torokhov To: Mark Brown Cc: Liam Girdwood , linux-kernel@vger.kernel.org, Bjorn Andersson Subject: [PATCH 4/4] regulator: core: make bulk API support optional supplies Date: Fri, 3 Feb 2017 15:16:19 -0800 Message-Id: <20170203231619.8013-4-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.11.0.483.g087da7b7c-goog In-Reply-To: <20170203231619.8013-1-dmitry.torokhov@gmail.com> References: <20170203231619.8013-1-dmitry.torokhov@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Make it possible to use the bulk API with optional supplies, by allowing the consumer to marking supplies as optional in the regulator_bulk_data. Based on earlier patch by Bjorn Andersson Signed-off-by: Dmitry Torokhov --- drivers/regulator/core.c | 41 ++++++++++++++++++++++++-------------- include/linux/regulator/consumer.h | 3 +++ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9eb2e04f1219..540d1dec6e06 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3546,20 +3546,22 @@ static int _notifier_call_chain(struct regulator_dev *rdev, int regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers) { + struct regulator *r; int i; int ret; - for (i = 0; i < num_consumers; i++) - consumers[i].consumer = NULL; - for (i = 0; i < num_consumers; i++) { - consumers[i].consumer = regulator_get(dev, - consumers[i].supply); - if (IS_ERR(consumers[i].consumer)) { - ret = PTR_ERR(consumers[i].consumer); + r = _regulator_get(dev, consumers[i].supply, + consumers[i].optional ? + OPTIONAL_GET : NORMAL_GET); + ret = PTR_ERR_OR_ZERO(r); + if (!ret) { + consumers[i].consumer = r; + } else if (ret == -ENODEV && consumers[i].optional) { + consumers[i].consumer = NULL; + } else { dev_err(dev, "Failed to get supply '%s': %d\n", consumers[i].supply, ret); - consumers[i].consumer = NULL; goto err; } } @@ -3568,7 +3570,8 @@ int regulator_bulk_get(struct device *dev, int num_consumers, err: while (--i >= 0) - regulator_put(consumers[i].consumer); + if (consumers[i].consumer) + regulator_put(consumers[i].consumer); return ret; } @@ -3601,7 +3604,7 @@ int regulator_bulk_enable(int num_consumers, int ret = 0; for (i = 0; i < num_consumers; i++) { - if (consumers[i].consumer->always_on) + if (!consumers[i].consumer || consumers[i].consumer->always_on) consumers[i].ret = 0; else async_schedule_domain(regulator_bulk_enable_async, @@ -3625,7 +3628,7 @@ int regulator_bulk_enable(int num_consumers, if (consumers[i].ret < 0) pr_err("Failed to enable %s: %d\n", consumers[i].supply, consumers[i].ret); - else + else if (consumers[i].consumer) regulator_disable(consumers[i].consumer); } @@ -3652,6 +3655,9 @@ int regulator_bulk_disable(int num_consumers, int ret, r; for (i = num_consumers - 1; i >= 0; --i) { + if (!consumers[i].consumer) + continue; + ret = regulator_disable(consumers[i].consumer); if (ret != 0) goto err; @@ -3662,6 +3668,9 @@ int regulator_bulk_disable(int num_consumers, err: pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); for (++i; i < num_consumers; ++i) { + if (!consumers[i].consumer) + continue; + r = regulator_enable(consumers[i].consumer); if (r != 0) pr_err("Failed to re-enable %s: %d\n", @@ -3693,8 +3702,8 @@ int regulator_bulk_force_disable(int num_consumers, int ret = 0; for (i = 0; i < num_consumers; i++) { - consumers[i].ret = - regulator_force_disable(consumers[i].consumer); + consumers[i].ret = consumers[i].consumer ? + regulator_force_disable(consumers[i].consumer) : 0; /* Store first error for reporting */ if (consumers[i].ret && !ret) @@ -3720,8 +3729,10 @@ void regulator_bulk_free(int num_consumers, int i; for (i = 0; i < num_consumers; i++) { - regulator_put(consumers[i].consumer); - consumers[i].consumer = NULL; + if (consumers[i].consumer) { + regulator_put(consumers[i].consumer); + consumers[i].consumer = NULL; + } } } EXPORT_SYMBOL_GPL(regulator_bulk_free); diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index ea0fffa5faeb..acaeeec279af 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -159,6 +159,8 @@ struct regulator; * * @supply: The name of the supply. Initialised by the user before * using the bulk regulator APIs. + * @optional: The supply should be considered optional. Initialised by the user + * before using the bulk regulator APIs. * @consumer: The regulator consumer for the supply. This will be managed * by the bulk API. * @@ -168,6 +170,7 @@ struct regulator; */ struct regulator_bulk_data { const char *supply; + bool optional; struct regulator *consumer; /* private: Internal use */ -- 2.11.0.483.g087da7b7c-goog