Received: by 10.223.164.221 with SMTP id h29csp2787965wrb; Wed, 18 Oct 2017 07:01:24 -0700 (PDT) X-Google-Smtp-Source: AOwi7QB0RuHe+3+mpJyt6Hb+zCSqJuxFL2EoZY3MKwcvkzwiStxuhIgCWg7duHZYWqKHPtVLy0MD X-Received: by 10.99.62.207 with SMTP id l198mr13629731pga.376.1508335283940; Wed, 18 Oct 2017 07:01:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508335283; cv=none; d=google.com; s=arc-20160816; b=aXYBsQaswaiV7Z6SGro6Ekqxr0xD1AWyymxxlbfcecIqOMpg2ikNHhn/lX36Sd+Mc/ K9WiItea55umwR/YrpINIabHJPg8Ht8Ps5q/amHyERbBquh2KMA4srWYJ8cdWcvRNjtj EA+wAa/k8hMghdSARIR4TrJuExcPbuKhOkKrIbId89u5hYWSpHl5TXwByrTe1kh+/exS v99dEFyxZC1ZY+uqLYadaX0YHWpkeAnqAUvG9QBRWB39KWjyAoRxxZGnJ67DBkaMDwGy VdRC3dLMA0knxsgXpFLf5XpaRLx/z72yfajnIu/4o9n78IoqBgme/scfP5qBT34J/XAw /1Dg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:cms-type:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=N04KPU1lXyOurXZdBs8ZLYxXwXslpNk0hGIEX+hJ5zw=; b=u6rQgow3jkXSejfTjxuzkTpZs6P7HUpil/5edlSfTfCj2diTdWGjuoYuOi5ntpQO38 h+KjMavAUgPLAWf5V12JcLJiT2J23ec4fdyVCpM8dsNcqKSGDlrH0dUfq0mtS4Fbakjp JZHUE15z0L2Hj/zfW+OBojkkiqAxu8eWyaUPerLSQQOCdn6rov6q5o2FQtrbgGXUreUy uB2uD0xTFPHuvNGgbB+6kJrfqbDJjC1e/QVYdmiVVRMXnyboP6+6u84zRt6ZZJjhNvow SXiW7WYmmQL6x5tzqMOWFVOSsCjQzuquirxEQ0seOqBtxtJm+unrKTpEUXIYe0sUCGlP jW+Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=samsung.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q13si6962283pgr.148.2017.10.18.07.01.09; Wed, 18 Oct 2017 07:01:23 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=samsung.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965707AbdJRMsD (ORCPT + 99 others); Wed, 18 Oct 2017 08:48:03 -0400 Received: from mailout2.w1.samsung.com ([210.118.77.12]:57372 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756421AbdJRMrl (ORCPT ); Wed, 18 Oct 2017 08:47:41 -0400 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20171018124739euoutp02627a26ec4ddae5304b70300dc9a3fe08~uquzTBwjd2353423534euoutp02G; Wed, 18 Oct 2017 12:47:39 +0000 (GMT) Received: from eusmges3.samsung.com (unknown [203.254.199.242]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20171018124738eucas1p15d317cc6ca3455342cad6bc0d48a3eec~uquyr7ZLy2010320103eucas1p1y; Wed, 18 Oct 2017 12:47:38 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges3.samsung.com (EUCPMTA) with SMTP id E6.7E.12867.A6D47E95; Wed, 18 Oct 2017 13:47:38 +0100 (BST) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20171018124737eucas1p2ed8002fa4910545e9d56a536303ffc12~uquyC0IIU0501905019eucas1p2f; Wed, 18 Oct 2017 12:47:37 +0000 (GMT) X-AuditID: cbfec7f2-f793b6d000003243-c9-59e74d6ac6ec Received: from eusync3.samsung.com ( [203.254.199.213]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id 94.8D.18832.96D47E95; Wed, 18 Oct 2017 13:47:37 +0100 (BST) Received: from AMDC2075.DIGITAL.local ([106.120.51.25]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OY000ISARIUEL70@eusync3.samsung.com>; Wed, 18 Oct 2017 13:47:37 +0100 (BST) From: Maciej Purski To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Cc: Mark Brown , Liam Girdwood , Rob Herring , Mark Rutland , Marek Szyprowski , Bartlomiej Zolnierkiewicz , Maciej Purski Subject: [RFC PATCH v2 3/3] regulator: core: Balance coupled regulators voltages Date: Wed, 18 Oct 2017 14:47:02 +0200 Message-id: <1508330822-8039-4-git-send-email-m.purski@samsung.com> X-Mailer: git-send-email 2.7.4 In-reply-to: <1508330822-8039-1-git-send-email-m.purski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrGIsWRmVeSWpSXmKPExsWy7djP87pZvs8jDW5dkrTYOGM9q8XUh0/Y LOYfOcdq8e1KB5PF5V1z2CwWvLzFYrH2yF12i6XXLzJZtO49wu7A6bFm3hpGj52z7rJ7bFrV yebRt2UVo8fnTXIBrFFcNimpOZllqUX6dglcGRe2zWEumJ1TcWbjcpYGxn1hXYycHBICJhJH Nx9ng7DFJC7cWw9kc3EICSxllDh6eiMLhPOZUWLC1Q0sMB3N06Yyg9hCAssYJdad44co+s8o cfPRKqB2Dg42AS2JNe3xIDUiAjYSb28cYASpYRaYxyQx9egksGZhgSCJnS9uMILYLAKqEisa /oIt4BVwlli7+gIzxDI5iZvnOsFsTgEXiUsbnjOBDJIQWMImsX3aAaiLXCT+TT4F1SAs8er4 FnYIW0ais+MgE4RdLXHx6y6oP2skGm9vgKqxlvg8aQtYL7MAn8SkbdOZQR6QEOCV6GgTgijx kHjUtQKq1VHi8pxjjBDPT2eUePkvbAKj9AJGhlWMIqmlxbnpqcXGesWJucWleel6yfm5mxiB sXv63/FPOxi/nrA6xCjAwajEwxug8ixSiDWxrLgy9xCjBAezkghvrMvzSCHelMTKqtSi/Pii 0pzU4kOM0hwsSuK8tlFtkUIC6YklqdmpqQWpRTBZJg5OqQbGObFLd8xQF7ydveL+zhiV1jwe 10N1fxbFzPlYd8rRqsWScdejry6d7MyZK7I/FahLSy3fvmY/y9aUqWsD4lrCf7n/niIXX+PD +s5ay0VqkfblP59q1Lsft5q+/vzkp4ivDYt+G7Pkxf2iW+uuqkb56dzJmZ9YErlkm7fAzmcn +Ze/Ez+jWBOkxFKckWioxVxUnAgABEMtHdkCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprLLMWRmVeSWpSXmKPExsVy+t/xq7qZvs8jDc6esbbYOGM9q8XUh0/Y LOYfOcdq8e1KB5PF5V1z2CwWvLzFYrH2yF12i6XXLzJZtO49wu7A6bFm3hpGj52z7rJ7bFrV yebRt2UVo8fnTXIBrFFcNimpOZllqUX6dglcGRe2zWEumJ1TcWbjcpYGxn1hXYycHBICJhLN 06YyQ9hiEhfurWfrYuTiEBJYwiix4kcDM4TTyCTx+/Mp9i5GDg42AS2JNe3xIA0iAjYSb28c YASpYRZYwCQx7esMsEnCAgESaw9uYgexWQRUJVY0/GUBsXkFnCXWrr4AtU1O4ua5TjCbU8BF 4tKG50wgthBQzdG+T2wTGHkXMDKsYhRJLS3OTc8tNtQrTswtLs1L10vOz93ECAy0bcd+bt7B eGlj8CFGAQ5GJR7eAJVnkUKsiWXFlbmHGCU4mJVEeGNdnkcK8aYkVlalFuXHF5XmpBYfYpTm YFES5+3dszpSSCA9sSQ1OzW1ILUIJsvEwSnVwGgrNL+Wf/eJjispRyoWTtA3kv1v9uP0lqWv JfY5Pvyt6Nqzq67c4Ng0bpPMG39apB6zLT75pZHxgmHB1PxEH/F5WsW/t9cxZ2/gr8m0sy45 E3i0wD3X/33x1rb/u6fW/ixkKU5O/Zi4Yb/erWr2iRNfmN3/5PDeOLeudFOK9b1LM7okw06y qCixFGckGmoxFxUnAgBd52OOMAIAAA== X-CMS-MailID: 20171018124737eucas1p2ed8002fa4910545e9d56a536303ffc12 X-Msg-Generator: CA X-Sender-IP: 182.198.249.179 X-Local-Sender: =?UTF-8?B?TWFjaWVqIFB1cnNraRtTZWN1cml0eSAoVFApG1NhbXN1bmcg?= =?UTF-8?B?RWxlY3Ryb25pY3MbVHJhaW5lZSAoKQ==?= X-Global-Sender: =?UTF-8?B?TWFjaWVqIFB1cnNraRtTZWN1cml0eSAoVFApG1NhbXN1bmcg?= =?UTF-8?B?RWxlY3Ryb25pY3MbVHJhaW5lZSAoKQ==?= X-Sender-Code: =?UTF-8?B?QzEwG0VIURtDMTBDRDAyQ0QwMjczOTU=?= CMS-TYPE: 201P X-CMS-RootMailID: 20171018124737eucas1p2ed8002fa4910545e9d56a536303ffc12 X-RootMTR: 20171018124737eucas1p2ed8002fa4910545e9d56a536303ffc12 References: <1508330822-8039-1-git-send-email-m.purski@samsung.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Odroid XU3/4 and other Exynos5422 based boards there is a case, that different devices on the board are supplied by different regulators with non-fixed voltages. If one of these devices temporarily requires higher voltage, there might occur a situation that the spread between two devices' voltages is so high, that there is a risk of changing 'high' and 'low' states on the interconnection between devices powered by those regulators. Introduce new function regulator_balance_coupled() which keeps max_spread constraint fulfilled between all coupled regulators. It should be called if any coupled regulator changes its voltage or after disabling or enabling. Disabled regulators should follow changes of the enabled ones and their consumers' demands shouldn't be taken into account while changing voltage of enabled regulators. Find voltages, which are closest to suiting all the consumers' demands while fulfilling max_spread constraint, keeping the following rules: - if one regulator is about to rise its voltage, rise others voltages if needed - if the regulator, which has caused rising other regulators, is lowered, lower the other regulators if possible - if one regulator is about to lower its voltage, but it hasn't caused rising other regulators, don't change its voltage if it's not allowed Change regulators' voltages step by step, keeping max_spread constraint fulfilled all the time. Function regulator_coupled_get_optimal_voltage() should find the best possible change for the regulator, which doesn't break max_spread constraint. In function regulator_balance_coupled_voltage() optimize number of steps by finding highest voltage difference on each iteration. Signed-off-by: Maciej Purski --- drivers/regulator/core.c | 292 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 276 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a6cf902..d2d910d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -107,6 +107,9 @@ 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); +static int regulator_set_voltage_rdev(struct regulator_dev *rdev, + int min_uV, int max_uV); +static int regulator_balance_coupled(struct coupled_reg_desc *c_desc); static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, const char *supply_name); @@ -185,6 +188,48 @@ static void regulator_unlock_supply(struct regulator_dev *rdev) } /** + * regulator_lock_coupled - lock a group of coupled regulators + * @c_desc: coupled regulators description source + */ +static void regulator_lock_coupled(struct coupled_reg_desc *c_desc) +{ + int n_coupled = c_desc->n_coupled; + int i; + + for (i = 0; i < n_coupled; i++) + mutex_lock_nested(&c_desc->coupled_rdevs[i]->mutex, i); +} + +/** + * regulator_unlock_coupled - unlock a group of coupled regulators + * @c_desc: coupled regulators description source + */ +static void regulator_unlock_coupled(struct coupled_reg_desc *c_desc) +{ + int n_coupled = c_desc->n_coupled; + int i; + + for (i = 0; i < n_coupled; i++) + mutex_unlock(&c_desc->coupled_rdevs[i]->mutex); +} + +static void regulator_lock_supply_parents(struct regulator_dev *rdev) +{ + struct regulator_dev *supply = rdev_get_supply(rdev); + + if (supply) + regulator_lock_supply(supply); +} + +static void regulator_unlock_supply_parents(struct regulator_dev *rdev) +{ + struct regulator_dev *supply = rdev_get_supply(rdev); + + if (supply) + regulator_unlock_supply(supply); +} + +/** * of_get_regulator - get a regulator device node based on supply name * @dev: Device pointer for the consumer (of regulator) device * @supply: regulator supply name @@ -2218,6 +2263,13 @@ int regulator_enable(struct regulator *regulator) if (ret != 0 && rdev->supply) regulator_disable(rdev->supply); + /* + * If the regulator is coupled with other regulators, we have to + * balance their voltages to keep the max_spread constraint. + */ + if (rdev->coupled_desc) + regulator_balance_coupled(rdev->coupled_desc); + return ret; } EXPORT_SYMBOL_GPL(regulator_enable); @@ -2323,6 +2375,13 @@ int regulator_disable(struct regulator *regulator) ret = _regulator_disable(rdev); mutex_unlock(&rdev->mutex); + /* + * If the regulator is coupled with other regulators, we can now + * balance their voltages without checking the disabled regulator. + */ + if (rdev->coupled_desc) + regulator_balance_coupled(rdev->coupled_desc); + if (ret == 0 && rdev->supply) regulator_disable(rdev->supply); @@ -2379,6 +2438,13 @@ int regulator_force_disable(struct regulator *regulator) while (rdev->open_count--) regulator_disable(rdev->supply); + /* + * If the regulator is coupled with other regulators, we can now + * balance their voltages without checking the disabled regulator. + */ + if (rdev->coupled_desc) + regulator_balance_coupled(rdev->coupled_desc); + return ret; } EXPORT_SYMBOL_GPL(regulator_force_disable); @@ -2460,10 +2526,9 @@ static int _regulator_is_enabled(struct regulator_dev *rdev) return rdev->desc->ops->is_enabled(rdev); } -static int _regulator_list_voltage(struct regulator *regulator, - unsigned selector, int lock) +static int _regulator_list_voltage(struct regulator_dev *rdev, + unsigned selector, int lock) { - struct regulator_dev *rdev = regulator->rdev; const struct regulator_ops *ops = rdev->desc->ops; int ret; @@ -2479,7 +2544,8 @@ static int _regulator_list_voltage(struct regulator *regulator, if (lock) mutex_unlock(&rdev->mutex); } else if (rdev->is_switch && rdev->supply) { - ret = _regulator_list_voltage(rdev->supply, selector, lock); + ret = _regulator_list_voltage(rdev->supply->rdev, + selector, lock); } else { return -EINVAL; } @@ -2555,7 +2621,7 @@ EXPORT_SYMBOL_GPL(regulator_count_voltages); */ int regulator_list_voltage(struct regulator *regulator, unsigned selector) { - return _regulator_list_voltage(regulator, selector, 1); + return _regulator_list_voltage(regulator->rdev, selector, 1); } EXPORT_SYMBOL_GPL(regulator_list_voltage); @@ -2896,8 +2962,6 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, int ret = 0; int old_min_uV, old_max_uV; int current_uV; - int best_supply_uV = 0; - int supply_change_uV = 0; /* If we're setting the same range as last time the change * should be a noop (some cpufreq implementations use the same @@ -2941,6 +3005,34 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, if (ret < 0) goto out2; + /* + * If the regulator is coupled, return after changing consumer demands + * without changing voltage. This will be handled outside the function + * by regulator_balance_coupled() + */ + if (rdev->coupled_desc) + goto out; + + ret = regulator_set_voltage_rdev(regulator->rdev, min_uV, max_uV); + if (ret < 0) + goto out2; + +out: + return 0; +out2: + regulator->min_uV = old_min_uV; + regulator->max_uV = old_max_uV; + + return ret; +} + +static int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV, + int max_uV) +{ + int best_supply_uV = 0; + int supply_change_uV = 0; + int ret; + if (rdev->supply && regulator_ops_is_valid(rdev->supply->rdev, REGULATOR_CHANGE_VOLTAGE) && @@ -2952,13 +3044,13 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, selector = regulator_map_voltage(rdev, min_uV, max_uV); if (selector < 0) { ret = selector; - goto out2; + goto out; } - best_supply_uV = _regulator_list_voltage(regulator, selector, 0); + best_supply_uV = _regulator_list_voltage(rdev, selector, 0); if (best_supply_uV < 0) { ret = best_supply_uV; - goto out2; + goto out; } best_supply_uV += rdev->desc->min_dropout_uV; @@ -2966,7 +3058,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); if (current_supply_uV < 0) { ret = current_supply_uV; - goto out2; + goto out; } supply_change_uV = best_supply_uV - current_supply_uV; @@ -2978,13 +3070,13 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, if (ret) { dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", ret); - goto out2; + goto out; } } ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); if (ret < 0) - goto out2; + goto out; if (supply_change_uV < 0) { ret = regulator_set_voltage_unlocked(rdev->supply, @@ -2998,9 +3090,174 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, out: return ret; -out2: - regulator->min_uV = old_min_uV; - regulator->max_uV = old_max_uV; +} + +static int regulator_coupled_get_optimal_voltage(struct regulator_dev *rdev) +{ + struct coupled_reg_desc *c_desc = rdev->coupled_desc; + struct regulator_dev **c_rdevs = c_desc->coupled_rdevs; + int max_spread = c_desc->max_spread; + int n_coupled = c_desc->n_coupled; + int desired_min_uV, desired_max_uV, min_actual_uV = INT_MAX; + int max_actual_uV = 0, highest_min_uV = 0, target_uV, possible_uV; + int i, ret; + + /* If consumers don't provide any demands, set voltage to min_uV */ + desired_min_uV = rdev->constraints->min_uV; + desired_max_uV = rdev->constraints->max_uV; + ret = regulator_check_consumers(rdev, + &desired_min_uV, + &desired_max_uV); + if (ret < 0) + goto out; + + /* Find highest min desired voltage */ + for (i = 0; i < n_coupled; i++) { + int tmp_min = 0; + int tmp_max = INT_MAX; + + if (!_regulator_is_enabled(c_rdevs[i])) + continue; + + ret = regulator_check_consumers(c_rdevs[i], + &tmp_min, + &tmp_max); + if (ret < 0) + goto out; + + if (tmp_min > highest_min_uV) + highest_min_uV = tmp_min; + } + + /* + * Let target_uV be equal to the desired one if possible. + * If not, set it to minimum voltage, allowed by other coupled + * regulators. + */ + target_uV = max(desired_min_uV, highest_min_uV - max_spread); + + /* + * Find min and max voltages, which currently aren't + * violating max_spread + */ + for (i = 0; i < n_coupled; i++) { + int tmp_act; + + /* + * Don't check the regulator, which is about + * to change voltage + */ + if (c_rdevs[i] == rdev) + continue; + if (!_regulator_is_enabled(c_rdevs[i])) + continue; + + tmp_act = _regulator_get_voltage(c_rdevs[i]); + if (tmp_act < 0) { + ret = tmp_act; + goto out; + } + + if (tmp_act < min_actual_uV) + min_actual_uV = tmp_act; + + if (tmp_act > max_actual_uV) + max_actual_uV = tmp_act; + } + + /* There aren't any other regulators enabled */ + if (max_actual_uV == 0) { + possible_uV = target_uV; + } else { + /* + * Correct target voltage, so as it currently isn't + * violating max_spread + */ + possible_uV = max(target_uV, max_actual_uV - max_spread); + possible_uV = min(possible_uV, min_actual_uV + max_spread); + } + + if (possible_uV > desired_max_uV) { + ret = -EINVAL; + goto out; + } + ret = possible_uV; + +out: + return ret; +} + +static int regulator_balance_coupled(struct coupled_reg_desc *c_desc) +{ + struct regulator_dev **c_rdevs = c_desc->coupled_rdevs; + int n_coupled = c_desc->n_coupled; + int i, best_delta, best_index, best_uV, ret = 1; + + /* + * Find the best possible voltage change on each loop. Leave the loop + * if there isn't any possible change. + */ + while (1) { + best_delta = 0; + best_uV = 0; + best_index = -1; + + regulator_lock_coupled(c_desc); + + /* + * Find highest difference between optimal voltage + * and actual voltage. + */ + for (i = 0; i < n_coupled; i++) { + /* + * optimal_uV is the best voltage that can be set for + * i-th regulator at the moment without violating + * max_spread constraint in order to balance + * the coupled voltages. + */ + int optimal_uV, actual_uV; + + optimal_uV = regulator_coupled_get_optimal_voltage(c_rdevs[i]); + if (optimal_uV < 0) { + ret = optimal_uV; + goto unlock; + } + + actual_uV = _regulator_get_voltage(c_rdevs[i]); + if (actual_uV < 0) { + ret = optimal_uV; + goto unlock; + } + + if (abs(best_delta) < abs(optimal_uV - actual_uV)) { + best_delta = optimal_uV - actual_uV; + best_index = i; + best_uV = optimal_uV; + } + } + + /* Nothing to change, return successfully */ + if (best_index == -1) { + ret = 0; + goto unlock; + } + /* + * Lock just the supply regulators, as the regulator itself + * is already locked by regulator_lock_coupled(). + */ + regulator_lock_supply_parents(c_rdevs[best_index]); + + ret = regulator_set_voltage_rdev(c_rdevs[best_index], best_uV, + best_uV); + + regulator_unlock_supply_parents(c_rdevs[best_index]); + +unlock: + regulator_unlock_coupled(c_desc); + + if (ret < 0 || best_index == -1) + break; + } return ret; } @@ -3033,6 +3290,9 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) regulator_unlock_supply(regulator->rdev); + if (regulator->rdev->coupled_desc) + ret = regulator_balance_coupled(regulator->rdev->coupled_desc); + return ret; } EXPORT_SYMBOL_GPL(regulator_set_voltage); -- 2.7.4 From 1585427997284604737@xxx Wed Nov 29 18:59:21 +0000 2017 X-GM-THRID: 1585254520936437003 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread