From patchwork Fri Jan 12 10:18:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chunyan Zhang X-Patchwork-Id: 124265 Delivered-To: patch@linaro.org Received: by 10.80.140.226 with SMTP id r31csp1693935edr; Fri, 12 Jan 2018 02:19:01 -0800 (PST) X-Google-Smtp-Source: ACJfBovjeurrCDL8KBKIE9Pu5quHj1nBxRqbLranluH/Nt5SEylC210/+QEHLC3kuf+WiFBVueZf X-Received: by 10.101.92.203 with SMTP id b11mr19764941pgt.177.1515752341119; Fri, 12 Jan 2018 02:19:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515752341; cv=none; d=google.com; s=arc-20160816; b=omPi6klypcq2Uz5auDs5YxwS1VR3+PaJ5wZ+QvE9J74+BNJy+yssfeEWTJBEektw2l JzeJXiW85J7Tn2H65y5ptvtPR5rG/pK6q0wI/FHLw1UcuyHCTGv/OYnyOXWqKYKozxK9 gib/vUk7kd6pIaE/+ziuiFpJQkPBaAkM78UqW//qYmg+3gqLDv997OAhrPRbm8PULA7z p8bhTKRvNaCZnn3LeEOaqZaA+9lE3h4ht8F2fz9WJhuAXZtrmjmYEMYKtcFpeMPyvt3P rHrvVCDtBs2EYa/cqRdLNQLviQso3k3TopaqmPYo85jlAxdVpB00HODABbvxl9byMA+i yziA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=wGI3NY6lEkBWVz+shP0kW0I+AbBcxdYAtIiEirYKySE=; b=RiIEmx5j0KKjSssS72l7nJe1SoPDxhuK1EX+R2y+jUJKW81CIRfBBZ938ug7nMxSqg 2S6J4vn75CRiElPbsu1U9Cc+y+OpckWQyyrPKqJpAEJF1MSDXUZYPrm3SYtbLHExjYZc woEsqzH1gBkBmovAMUI2dlcYRQAW8JZODHK8wnDy7TUrRZnGSdkW5TlObFQAFeE/22DU v5thQbxW5Sf5Z34PXYCi0fVaDTdWtvf/oaKi6jOtmfJD0BAm+xaevQ2dktLt9EL+Ic4z nK1AV1V2zixvSPK27X1uUtDwj+FakEtI0HL5TRKSRHnYBM2hxqTEGx/HIdR0t+LawLuW yZQQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=A+VPRBAh; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h1si13416734pgs.693.2018.01.12.02.19.00; Fri, 12 Jan 2018 02:19:01 -0800 (PST) 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; dkim=pass header.i=@linaro.org header.s=google header.b=A+VPRBAh; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754824AbeALKS6 (ORCPT + 28 others); Fri, 12 Jan 2018 05:18:58 -0500 Received: from mail-pg0-f66.google.com ([74.125.83.66]:34490 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754784AbeALKSz (ORCPT ); Fri, 12 Jan 2018 05:18:55 -0500 Received: by mail-pg0-f66.google.com with SMTP id j4so4307049pgp.1 for ; Fri, 12 Jan 2018 02:18:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wGI3NY6lEkBWVz+shP0kW0I+AbBcxdYAtIiEirYKySE=; b=A+VPRBAhoPQMPHYZ01XBT4Q16VivPgyVAbltdTsDHjDZnOJsYnleGe7nTmLphilACF Nldgm/F9EtTCeMJ6O3V7P2QitItNTfyA4IY2wmySuj0AH7N0+nZP0okq6LnfNLAugo+0 WPW5KazGGWFxXzIyLTznMT0ltfgenwZy3Njxs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wGI3NY6lEkBWVz+shP0kW0I+AbBcxdYAtIiEirYKySE=; b=E1uK6PmpqqG4f6L740p5yh5fBWj7h/EVdvP/CXu5SvzqUMwO8jd/gaiw1DPK23WYEF i7Dqy8V+o4Emurk5C61NfT4vj85t/VlqhSL2vlR/nw4m+UDJHvF7dTtCic548M9n9HnM sxMRIY5uI3+d6fpAa5vRhYSKuw4pYiar8I5qOIUDNCYlwtEqa1HagozLoPbL8NzRP9aC 5GrNLX9bXCp/A/RgmmHOMeRtHbKig/eZCjUlbrE5/E0VvRqCY49j7Fwk8n5rYAVmZJ07 mbVIrHsCU1xAqW5C7q34cGHSU01cnLDYjqnA4xU2zyoyCR50RaevUwLF+2w2xLc9iygQ WMqg== X-Gm-Message-State: AKwxytf+xY6ok2geQYHu/RG1SkjGwZo0T2vBPa2H838oiaBLXr/gvShC oBpibMihy78MaL2BqqRMsks7sQ== X-Received: by 10.159.197.73 with SMTP id d9mr9118940plo.121.1515752334672; Fri, 12 Jan 2018 02:18:54 -0800 (PST) Received: from ubt.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id m22sm44692613pfg.120.2018.01.12.02.18.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 12 Jan 2018 02:18:53 -0800 (PST) From: Chunyan Zhang To: Mark Brown , Rob Herring Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Ulf Hansson , Arnd Bergmann , Chunyan Zhang Subject: [PATCH v3 1/5] bindings: regulator: added support for suspend states Date: Fri, 12 Jan 2018 18:18:21 +0800 Message-Id: <1515752305-15907-2-git-send-email-zhang.chunyan@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515752305-15907-1-git-send-email-zhang.chunyan@linaro.org> References: <1515752305-15907-1-git-send-email-zhang.chunyan@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Some systems need to set regulators to specific states when they enter low power modes, especially around CPUs. There are many of these modes depending on the particular runtime state. Currently the regulator consumers are not granted permission to change suspend state of regulator devices, the constraints are configured at startup. In order to allow changes in a vlotage range, we need to add new properties for voltage range and a flag to give permission to change the suspend voltage and suspend on/off in suspend mode. Signed-off-by: Chunyan Zhang --- Documentation/devicetree/bindings/regulator/regulator.txt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) -- 2.7.4 diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 378f6dc..532e286 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -42,8 +42,19 @@ Optional properties: - regulator-state-[mem/disk] node has following common properties: - regulator-on-in-suspend: regulator should be on in suspend state. - regulator-off-in-suspend: regulator should be off in suspend state. - - regulator-suspend-microvolt: regulator should be set to this voltage - in suspend. + - regulator-suspend-min-microvolt: minimum voltage may be set in + suspend state. + - regulator-suspend-max-microvolt: maximum voltage may be set in + suspend state. + - regulator-suspend-microvolt: the default voltage which regulator + would be set in suspend. The voltage for suspend also can be + adjusted among {regulator-suspend-min-microvolt, + regulator-suspend-max-microvolt} by calling + regulator_set_suspend_voltage(). This property is now deprecated, + setting voltage for suspend mode via API the regulator driver + provides is recommended. + - regulator-changeable-in-suspend: whether the default voltage and + the regulator on/off in suspend can be changed in runtime. - regulator-mode: operating mode in the given suspend state. The set of possible operating modes depends on the capabilities of every hardware so the valid modes are documented on each regulator From patchwork Fri Jan 12 10:18:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chunyan Zhang X-Patchwork-Id: 124266 Delivered-To: patch@linaro.org Received: by 10.80.140.226 with SMTP id r31csp1694039edr; Fri, 12 Jan 2018 02:19:07 -0800 (PST) X-Google-Smtp-Source: ACJfBosenNkWxLxJloL9FiZXXxOBAYjT8BnRVzI3pqFRbtxlF2eChzrO4UaVARR7ZHG7UsKBAZR6 X-Received: by 10.99.95.76 with SMTP id t73mr18904963pgb.310.1515752347684; Fri, 12 Jan 2018 02:19:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515752347; cv=none; d=google.com; s=arc-20160816; b=sspaZvh4G1r/OZXXlD4acVcikmtnqkHmDWMz1b0QXn6qAA3NUdim6h61U6gMTaU3Yv E0ZoONMQWgk6vit3Fnagn4zVo+GFpae6AhhjrrXeayw/veaGEEmMjEHlr3xMO33PrjiW kV7ex6olXVyHppT5qCHtgUAGgy9e2aaroqGqtkVFVpN59lvQTeh94cizqWpWwiWxCmWR n+ReZCrPXDFI43c6m8XNGT19LZmtmUXCrEpQ+lLCiKL4xCHFCYhoVKs+P7bDZ8nVPXCs JJE0OZT9jTzGBYdipXvwmodYKLs1YVK4gRKlD+gcRENAIfCjx80URRzKJvU1v2PEgpmR +ldg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=7bkU8d6OAw4dJNJomrati/RpvribAE2V8BOdwc88N+k=; b=BTvXKUsBtowEKHNFK8ZkbWt+HBxCbK1SjKl6V1ZXqtwKZR9KyXa6VQm+KSfp5iIbs/ YEZq+D/e0asAZ8U+r35WtdSpRMJhFYAT4Stl7BTUxJ6D2TOkcMOQCYxkJxx+2NqRQd/E Vbzbl+WpyaoViTBKsW/kOcnw1iqK4tqYJ9Pq22nk6ym4xFdYgsaab66EZHBHSL2Bc4+1 hY+VXbfTJ2sEm6yrB0OqWn5uPdOzOTCl3GMCnJ9mWw3aND504+j3qtSCDciQA+NyF8M9 3wESePYBcFUEwWOJFhhr0EGj3HAocMMhyaisxoEg2PJVWS1LPLcjkWCcjiJtJ7XrR6xd 68Lw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZeseZVRu; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z82si15151626pfd.233.2018.01.12.02.19.07; Fri, 12 Jan 2018 02:19:07 -0800 (PST) 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; dkim=pass header.i=@linaro.org header.s=google header.b=ZeseZVRu; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933064AbeALKTF (ORCPT + 28 others); Fri, 12 Jan 2018 05:19:05 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:34264 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754831AbeALKS7 (ORCPT ); Fri, 12 Jan 2018 05:18:59 -0500 Received: by mail-pf0-f196.google.com with SMTP id e76so4082775pfk.1 for ; Fri, 12 Jan 2018 02:18:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7bkU8d6OAw4dJNJomrati/RpvribAE2V8BOdwc88N+k=; b=ZeseZVRuPdUAL7aKqvYKtLYWp8VglpQyrWHFXespAy8NquVQBCDxsXpAPViaNieA6t bowbdDkQ7u+RT6ti1NLHX2O2SMpZFanrBzJPTeP7O0l03DowpZfGpmHyou8Pb3G+eNq4 4R1tDr+f+2wCdolL2DR+u+xTWhToXUlndUZTQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7bkU8d6OAw4dJNJomrati/RpvribAE2V8BOdwc88N+k=; b=jdFjZoz+GTDe6NMDHg0g7Ph4pSYKxw+ZpXzDmEx1G5Mf7BX5L4By8oYtEnxrlKW434 zTguAPEZ1aL7jchyVKrSYkDdkOa+DJzeTXr8hr4I3u0WXvBHLPQajwA0N32+2dL4CugB ymjJl/TNhnidK0f3vJ+6/xR8ARCoDP1An49dv7D3XMvfXtxshpcL6CkTMQN/M6CHndKH LWsWgAEhAq+3B43RPh2W+I52heTYasiZ/hzHhwL/GyXmhMj9vasjalK4JgbDVsahe8hT iDuOo90xqo3bvEK8qVg180433pOr57EbZ+z9YaSaWC6MqA//Dg94R6BqyJeYRt99KZf8 v3rA== X-Gm-Message-State: AKGB3mJNlltteY4O0p92SRMPrlkFCnBSpnI+6o6oGTdDLkwOuWsunQ9V bJA5mh3emCQesN5L6gfUuYXnUg== X-Received: by 10.99.144.76 with SMTP id a73mr17679661pge.376.1515752338551; Fri, 12 Jan 2018 02:18:58 -0800 (PST) Received: from ubt.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id m22sm44692613pfg.120.2018.01.12.02.18.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 12 Jan 2018 02:18:57 -0800 (PST) From: Chunyan Zhang To: Mark Brown , Rob Herring Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Ulf Hansson , Arnd Bergmann , Chunyan Zhang Subject: [PATCH v3 2/5] regulator: make regulator voltage be an array to support more states Date: Fri, 12 Jan 2018 18:18:22 +0800 Message-Id: <1515752305-15907-3-git-send-email-zhang.chunyan@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515752305-15907-1-git-send-email-zhang.chunyan@linaro.org> References: <1515752305-15907-1-git-send-email-zhang.chunyan@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Some regulator consumers would like to make the regulator device keeping a voltage range output when the system entering into suspend states. Making regulator voltage be an array can allow consumers to set voltage for normal state as well as for suspend states through the same code. Signed-off-by: Chunyan Zhang --- drivers/regulator/core.c | 63 ++++++++++++++++++++++++-------------------- drivers/regulator/internal.h | 18 +++++++++++-- 2 files changed, 51 insertions(+), 30 deletions(-) -- 2.7.4 diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index b64b791..97bc9f7 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -240,22 +240,25 @@ static int regulator_check_voltage(struct regulator_dev *rdev, * regulator consumers */ static int regulator_check_consumers(struct regulator_dev *rdev, - int *min_uV, int *max_uV) + int *min_uV, int *max_uV, + suspend_state_t state) { struct regulator *regulator; + struct regulator_voltage *voltage; list_for_each_entry(regulator, &rdev->consumer_list, list) { + voltage = ®ulator->voltage[state]; /* * Assume consumers that didn't say anything are OK * with anything in the constraint range. */ - if (!regulator->min_uV && !regulator->max_uV) + if (!voltage->min_uV && !voltage->max_uV) continue; - if (*max_uV > regulator->max_uV) - *max_uV = regulator->max_uV; - if (*min_uV < regulator->min_uV) - *min_uV = regulator->min_uV; + if (*max_uV > voltage->max_uV) + *max_uV = voltage->max_uV; + if (*min_uV < voltage->min_uV) + *min_uV = voltage->min_uV; } if (*min_uV > *max_uV) { @@ -1356,9 +1359,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, debugfs_create_u32("uA_load", 0444, regulator->debugfs, ®ulator->uA_load); debugfs_create_u32("min_uV", 0444, regulator->debugfs, - ®ulator->min_uV); + ®ulator->voltage[PM_SUSPEND_ON].min_uV); debugfs_create_u32("max_uV", 0444, regulator->debugfs, - ®ulator->max_uV); + ®ulator->voltage[PM_SUSPEND_ON].max_uV); debugfs_create_file("constraint_flags", 0444, regulator->debugfs, regulator, &constraint_flags_fops); @@ -2898,9 +2901,11 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } static int regulator_set_voltage_unlocked(struct regulator *regulator, - int min_uV, int max_uV) + int min_uV, int max_uV, + suspend_state_t state) { struct regulator_dev *rdev = regulator->rdev; + struct regulator_voltage *voltage = ®ulator->voltage[state]; int ret = 0; int old_min_uV, old_max_uV; int current_uV; @@ -2911,7 +2916,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, * should be a noop (some cpufreq implementations use the same * voltage for multiple frequencies, for example). */ - if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) + if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) goto out; /* If we're trying to set a range that overlaps the current voltage, @@ -2921,8 +2926,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { current_uV = _regulator_get_voltage(rdev); if (min_uV <= current_uV && current_uV <= max_uV) { - regulator->min_uV = min_uV; - regulator->max_uV = max_uV; + voltage->min_uV = min_uV; + voltage->max_uV = max_uV; goto out; } } @@ -2940,12 +2945,12 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, goto out; /* restore original values in case of error */ - old_min_uV = regulator->min_uV; - old_max_uV = regulator->max_uV; - regulator->min_uV = min_uV; - regulator->max_uV = max_uV; + old_min_uV = voltage->min_uV; + old_max_uV = voltage->max_uV; + voltage->min_uV = min_uV; + voltage->max_uV = max_uV; - ret = regulator_check_consumers(rdev, &min_uV, &max_uV); + ret = regulator_check_consumers(rdev, &min_uV, &max_uV, state); if (ret < 0) goto out2; @@ -2982,7 +2987,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, if (supply_change_uV > 0) { ret = regulator_set_voltage_unlocked(rdev->supply, - best_supply_uV, INT_MAX); + best_supply_uV, INT_MAX, state); if (ret) { dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", ret); @@ -2996,7 +3001,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, if (supply_change_uV < 0) { ret = regulator_set_voltage_unlocked(rdev->supply, - best_supply_uV, INT_MAX); + best_supply_uV, INT_MAX, state); if (ret) dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", ret); @@ -3007,8 +3012,8 @@ 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; + voltage->min_uV = old_min_uV; + voltage->max_uV = old_max_uV; return ret; } @@ -3037,7 +3042,8 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) regulator_lock_supply(regulator->rdev); - ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); + ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, + PM_SUSPEND_ON); regulator_unlock_supply(regulator->rdev); @@ -3138,6 +3144,7 @@ EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); int regulator_sync_voltage(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; + struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; int ret, min_uV, max_uV; mutex_lock(&rdev->mutex); @@ -3149,20 +3156,20 @@ int regulator_sync_voltage(struct regulator *regulator) } /* This is only going to work if we've had a voltage configured. */ - if (!regulator->min_uV && !regulator->max_uV) { + if (!voltage->min_uV && !voltage->max_uV) { ret = -EINVAL; goto out; } - min_uV = regulator->min_uV; - max_uV = regulator->max_uV; + min_uV = voltage->min_uV; + max_uV = voltage->max_uV; /* This should be a paranoia check... */ ret = regulator_check_voltage(rdev, &min_uV, &max_uV); if (ret < 0) goto out; - ret = regulator_check_consumers(rdev, &min_uV, &max_uV); + ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); if (ret < 0) goto out; @@ -4424,8 +4431,8 @@ static void regulator_summary_show_subtree(struct seq_file *s, switch (rdev->desc->type) { case REGULATOR_VOLTAGE: seq_printf(s, "%37dmV %5dmV", - consumer->min_uV / 1000, - consumer->max_uV / 1000); + consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, + consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); break; case REGULATOR_CURRENT: break; diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 66a8ea0..aba8e414 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -16,10 +16,25 @@ #ifndef __REGULATOR_INTERNAL_H #define __REGULATOR_INTERNAL_H +#include + +#define REGULATOR_STATES_NUM (PM_SUSPEND_MAX + 1) + +struct regulator_voltage { + int min_uV; + int max_uV; +}; + /* * struct regulator * * One for each consumer device. + * @voltage - a voltage array for each state of runtime, i.e.: + * PM_SUSPEND_ON + * PM_SUSPEND_TO_IDLE + * PM_SUSPEND_STANDBY + * PM_SUSPEND_MEM + * PM_SUSPEND_MAX */ struct regulator { struct device *dev; @@ -27,8 +42,7 @@ struct regulator { unsigned int always_on:1; unsigned int bypass:1; int uA_load; - int min_uV; - int max_uV; + struct regulator_voltage voltage[REGULATOR_STATES_NUM]; const char *supply_name; struct device_attribute dev_attr; struct regulator_dev *rdev; From patchwork Fri Jan 12 10:18:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chunyan Zhang X-Patchwork-Id: 124269 Delivered-To: patch@linaro.org Received: by 10.80.140.226 with SMTP id r31csp1694718edr; Fri, 12 Jan 2018 02:19:48 -0800 (PST) X-Google-Smtp-Source: ACJfBosFBLAJu9FN3w4Yj1APnmO95pJEfvAJbk7mcHQ2hp6zcJ7ufhJeOYpHj0bYNfRLVaXnw+hW X-Received: by 10.84.246.12 with SMTP id k12mr4952044pll.438.1515752387883; Fri, 12 Jan 2018 02:19:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515752387; cv=none; d=google.com; s=arc-20160816; b=JmHeKtjkl9pyemkLl6AE3hcxbByLDTsxFDhy1cWaF7KqdvqqEyb2w9TMItvOoQ7igH OqhVULzoq2GgqMbjTyyos381UNw0BKgspFMg1l8UN/p+F/5q71SbJZN9o1v/LWV7KAvQ mtq+EYfphAygkvq/gLYui48V59LLlgxbxn8s5+mAzc2IeQiXTAssf65acx62V1OMSGWh SJmcTUAwf5CT7WAOsec3wWSPVFd/2OB+3Nra3QEdp072V5wwdoAWuXyb/qppnzu/g31l ZWKSf5aMoVrSJIonofVv/oks5bVOoRTOuakPRzbBfhgQDpq92gAHohmYQZ/A76aMKE5u PQzg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=EcLpvBMIMakiKa8EPdDMFEkOKTKDf++0HWt3W/KiWU4=; b=Q6PHdcvuB1ZVTQ9cH+cV/22PDsHCD2I3u60LPTLVv5iSDtAsCgGfkMhfIGgXtMhO01 +0O6VY2ONiNI45KNDp48ax6mrMYMAk8bi7gGpEMVMKgXUs2A8W+Hjb/3+mgc95Vw/4Yb WVHxUOjtqYHet79NvEgKQ+8h83sA8N5hQ8UAhhcIxUUFWNHYfUnL+ikkZrQ59FIDjMj8 q76HPR4qDEq6wQqlzjzLB6LyDQYd3HVklNheD9clF+uZKkiosrVhR7J2k85QwZqUgXHa 2DMek73uPMYrO1PMzP1X001gIR9w2fi30C9xmDxjuak0xgEpzbtYYXqY1FSABsAYyBFK 8l4Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=KLmEU2VB; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l6si13445687pgr.804.2018.01.12.02.19.47; Fri, 12 Jan 2018 02:19:47 -0800 (PST) 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; dkim=pass header.i=@linaro.org header.s=google header.b=KLmEU2VB; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933429AbeALKTp (ORCPT + 28 others); Fri, 12 Jan 2018 05:19:45 -0500 Received: from mail-pf0-f195.google.com ([209.85.192.195]:44008 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754833AbeALKTC (ORCPT ); Fri, 12 Jan 2018 05:19:02 -0500 Received: by mail-pf0-f195.google.com with SMTP id e3so4084840pfi.10 for ; Fri, 12 Jan 2018 02:19:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=EcLpvBMIMakiKa8EPdDMFEkOKTKDf++0HWt3W/KiWU4=; b=KLmEU2VBqUhD9+TwhU9dji27xdf//pgTjaUFkKlgHxv4vJqFkc64GvmbbKbZbuzWgH G4P/s3KD2+v3Oscf8PnpXx06j0vD7pdx8Y+1Y9ZS8yjlv/CZIGfhMrpvkqF4nRtvLFnr NYu5hUPVH45A+uYbhV1nOR0zEfSlX75Gl1GsA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=EcLpvBMIMakiKa8EPdDMFEkOKTKDf++0HWt3W/KiWU4=; b=OUX5gO4Og0TsvT3UT2q7mdLY+fhkqeMzxKGC0D8yfGG/JoNpisNnBJlGNUE9immv/+ +fLQHxaDk7eLJvq4kRa50ZZYJuC0Kznt6m4+CcdbM8oRhE1FSs4NXkB5u4URbFuu8WUZ M2Ux7QrVHPIDY9wR11N1YSEbjQLYZFuPdUHEwV5ESdKwECg/29RKbRd5rONmRx2dWvBz Oc49Z8if0L8mU9xZ+VJMkC1CImQngYMVp24fhlcYvY4eajY+BTMgi+LC8vfCljp6CnnQ Xf5xJZL8XFKi9liX0bOgr6KXU826ZsLr8klefTBNHD3UTIQq25IeLdEwNwqOQKw4fnfi dG4A== X-Gm-Message-State: AKGB3mK9hmjLk/RuEsPeo578S8BYueJ9Bs2gC6izxjFeEC9swa5saupz 4/DhLB4yUpVGv24b2F0j5U9jGA== X-Received: by 10.159.204.131 with SMTP id t3mr25942874plo.381.1515752341773; Fri, 12 Jan 2018 02:19:01 -0800 (PST) Received: from ubt.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id m22sm44692613pfg.120.2018.01.12.02.18.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 12 Jan 2018 02:19:00 -0800 (PST) From: Chunyan Zhang To: Mark Brown , Rob Herring Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Ulf Hansson , Arnd Bergmann , Chunyan Zhang Subject: [PATCH v3 3/5] drivers: regulator: leave one item to record whether regulator is enabled Date: Fri, 12 Jan 2018 18:18:23 +0800 Message-Id: <1515752305-15907-4-git-send-email-zhang.chunyan@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515752305-15907-1-git-send-email-zhang.chunyan@linaro.org> References: <1515752305-15907-1-git-send-email-zhang.chunyan@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The items "disabled" and "enabled" are a little redundant, since only one of them would be set to record if the regulator device should keep on or be switched to off in suspend states. So in this patch, the "disabled" was removed, only leave the "enabled": - enabled == 1 for regulator-on-in-suspend - enabled == 0 for regulator-off-in-suspend - enabled == -1 means do nothing when entering suspend mode. Signed-off-by: Chunyan Zhang --- drivers/regulator/core.c | 14 ++++++-------- drivers/regulator/of_regulator.c | 6 ++++-- include/linux/regulator/machine.h | 19 +++++++++++++++---- 3 files changed, 25 insertions(+), 14 deletions(-) -- 2.7.4 diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 97bc9f7..5ea80e9 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -742,21 +742,19 @@ static int suspend_set_state(struct regulator_dev *rdev, * only warn if the driver implements set_suspend_voltage or * set_suspend_mode callback. */ - if (!rstate->enabled && !rstate->disabled) { + if (rstate->enabled != ENABLE_IN_SUSPEND && + rstate->enabled != DISABLE_IN_SUSPEND) { if (rdev->desc->ops->set_suspend_voltage || rdev->desc->ops->set_suspend_mode) rdev_warn(rdev, "No configuration\n"); return 0; } - if (rstate->enabled && rstate->disabled) { - rdev_err(rdev, "invalid configuration\n"); - return -EINVAL; - } - - if (rstate->enabled && rdev->desc->ops->set_suspend_enable) + if (rstate->enabled == ENABLE_IN_SUSPEND && + rdev->desc->ops->set_suspend_enable) ret = rdev->desc->ops->set_suspend_enable(rdev); - else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) + else if (rstate->enabled == DISABLE_IN_SUSPEND && + 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 */ ret = 0; diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 14637a0..41dad42 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -177,10 +177,12 @@ static void of_get_regulation_constraints(struct device_node *np, if (of_property_read_bool(suspend_np, "regulator-on-in-suspend")) - suspend_state->enabled = true; + suspend_state->enabled = ENABLE_IN_SUSPEND; else if (of_property_read_bool(suspend_np, "regulator-off-in-suspend")) - suspend_state->disabled = true; + suspend_state->enabled = DISABLE_IN_SUSPEND; + else + suspend_state->enabled = DO_NOTHING_IN_SUSPEND; if (!of_property_read_u32(suspend_np, "regulator-suspend-microvolt", &pval)) diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 9cd4fef..ce89c55 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -42,6 +42,16 @@ struct regulator; #define REGULATOR_CHANGE_DRMS 0x10 #define REGULATOR_CHANGE_BYPASS 0x20 +/* + * operations in suspend mode + * DO_NOTHING_IN_SUSPEND - the default value + * DISABLE_IN_SUSPEND - turn off regulator in suspend states + * ENABLE_IN_SUSPEND - keep regulator on in suspend states + */ +#define DO_NOTHING_IN_SUSPEND (-1) +#define DISABLE_IN_SUSPEND 0 +#define ENABLE_IN_SUSPEND 1 + /* Regulator active discharge flags */ enum regulator_active_discharge { REGULATOR_ACTIVE_DISCHARGE_DEFAULT, @@ -58,14 +68,15 @@ enum regulator_active_discharge { * * @uV: Operating voltage during suspend. * @mode: Operating mode during suspend. - * @enabled: Enabled during suspend. - * @disabled: Disabled during suspend. + * @enabled: operations during suspend. + * - DO_NOTHING_IN_SUSPEND + * - DISABLE_IN_SUSPEND + * - ENABLE_IN_SUSPEND */ struct regulator_state { int uV; /* suspend voltage */ unsigned int mode; /* suspend regulator operating mode */ - int enabled; /* is regulator enabled in this suspend state */ - int disabled; /* is the regulator disabled in this suspend state */ + int enabled; }; /** From patchwork Fri Jan 12 10:18:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chunyan Zhang X-Patchwork-Id: 124268 Delivered-To: patch@linaro.org Received: by 10.80.140.226 with SMTP id r31csp1694171edr; Fri, 12 Jan 2018 02:19:15 -0800 (PST) X-Google-Smtp-Source: ACJfBosaHdmM8iAcSPkLfTNSkNfuQgXskrgGZXiiQOiQZco8gSgt45rbRgYhpDULlyqlO8Zwmccf X-Received: by 10.99.128.66 with SMTP id j63mr10273590pgd.254.1515752355587; Fri, 12 Jan 2018 02:19:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515752355; cv=none; d=google.com; s=arc-20160816; b=sAGB5H8aqx9SLA3GTxZnDwZ/DRZ3SNqP+5DnKrGlOo/4isiF5IwcDGvSO7BJC0xO+x En2BXQJl+qnGu99eNQkT1SL/mzxXcNDHKD4nSjToruv80J5l+HBDJyxwE+v1VtM/2ozp yz7h5SHRozU9Mh1ZFyl/s7kqZvdddKRdrqZzYijId64A0cUxZc/9iSsRPv5y4kbCNzTC Vd3WhYDNbBtAWi55Hjn34GpGpOwUSktAKRlzA35YR9OUqwsx4RdLabAUfA/Zr207Bn3v JWlRUqJ6yRNq9hkUsezQfwaVthnLkkWYmZ9BxlIhqBYn1gl23C8qiNEoX/3q1kOc8Ufc aC8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=IWJ3mszr09oNqlYiPcCcomDRoYXzAaNJhfoCNZJ3bsQ=; b=OphOAHlV5mfjMrQXb4QJ1D0uXWmLMiCdeV9ctgf4yWPwe3+S09bfdLhUuHgtTZmpS/ GC+2ZJQ13igjt8MsiWd7lnyec/qpYod/DGqUuqooJgNCkh9JUUjn8oarqrHxIZIcAe5b WRsJrlUZQBH05aijV0q/w+tX+ydPZ7WUHH56V8D4nn9wb8CjwgSjq5yVXyjjhJ4g2ThW 3E5vJhVbbIZIZlYRjE3FpvB+dK6wOABtW4LiAqJVvnJzQlSMInPdp8iYvqFRmFiRjDFG N+ulnNoBCP6JxGJjCREMBs/BsYpWh/ETr6Wpl1zHlJatUFntOi6aWHJLtcINMogA9SS5 07DA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=QdRTdKDQ; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b35si15501079plh.55.2018.01.12.02.19.15; Fri, 12 Jan 2018 02:19:15 -0800 (PST) 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; dkim=pass header.i=@linaro.org header.s=google header.b=QdRTdKDQ; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933355AbeALKTN (ORCPT + 28 others); Fri, 12 Jan 2018 05:19:13 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:44945 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933094AbeALKTJ (ORCPT ); Fri, 12 Jan 2018 05:19:09 -0500 Received: by mail-pg0-f65.google.com with SMTP id m20so4264866pgc.11 for ; Fri, 12 Jan 2018 02:19:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=IWJ3mszr09oNqlYiPcCcomDRoYXzAaNJhfoCNZJ3bsQ=; b=QdRTdKDQM+65tvKjYofnVpc/0IcAxhXBFBLWQJR3ZWV2EolQyLuhmq3e2Zg9jze0ir rb5+3oaTAlM71F+FngJ/B9do51lHEU28pwn0x+Bl52H49gMbmOthexcKV1YAZxF/5Vhi Wh3pj054TARMI8GpBCOk6ZHFmvQ6cmkCvT+fY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=IWJ3mszr09oNqlYiPcCcomDRoYXzAaNJhfoCNZJ3bsQ=; b=Tx8rwa6+NcSAtGCajW91E/JBk0T8BZFUfmQH3LQQ76AcPM8nM+cePT5u2v5NBGRhIJ 5KVOzWYE68Y3giy6CIOqRRjGoU67mQfBvLADPvVqLaHacfXNV4lcMlrBDqvfypSn7Lwu QLjEYnkqm3D7OTFK34INn284icMiImpPnjVySjdASnoHhko18HjS8bcy90z3bh/4mUWt fG22WW3f6Y6naFIABn5du/V10t8YMRjAAyZQNhuqE3mWLdLpEnDRjreQtrGPoD6Uy4qr wj7/1SmoofyVdtr90n6hZd23vPG/BC0v/7oHxoXNDnqvJyPrScibbnGiy3463c+2VwjW 4w5w== X-Gm-Message-State: AKGB3mKzojctlV4LhqboIAeWi7T7arKiIo12ktWGX6a5hqmopnNImiJS gDg8PdfKlEpO5tu7uTIfPh+7gFSwI4I= X-Received: by 10.84.211.105 with SMTP id b96mr25511945pli.451.1515752349131; Fri, 12 Jan 2018 02:19:09 -0800 (PST) Received: from ubt.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id m22sm44692613pfg.120.2018.01.12.02.19.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 12 Jan 2018 02:19:08 -0800 (PST) From: Chunyan Zhang To: Mark Brown , Rob Herring Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Ulf Hansson , Arnd Bergmann , Chunyan Zhang Subject: [PATCH v3 5/5] regulator: add PM suspend and resume hooks Date: Fri, 12 Jan 2018 18:18:25 +0800 Message-Id: <1515752305-15907-6-git-send-email-zhang.chunyan@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515752305-15907-1-git-send-email-zhang.chunyan@linaro.org> References: <1515752305-15907-1-git-send-email-zhang.chunyan@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In this patch, consumers are allowed to set suspend voltage, and this actually just set the "uV" in constraint::regulator_state, when the regulator_suspend_late() was called by PM core through callback when the system is entering into suspend, the regulator device would act suspend activity then. And it assumes that if any consumer set suspend voltage, the regulator device should be enabled in the suspend state. And if the suspend voltage of a regulator device for all consumers was set zero, the regulator device would be off in the suspend state. This patch also provides a new function hook to regulator devices for resuming from suspend states. Signed-off-by: Chunyan Zhang --- drivers/regulator/core.c | 245 +++++++++++++++++++++++++++++++++----- drivers/regulator/of_regulator.c | 14 +++ include/linux/regulator/driver.h | 2 + include/linux/regulator/machine.h | 13 +- 4 files changed, 241 insertions(+), 33 deletions(-) -- 2.7.4 diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 080c233..0dfa758 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -236,6 +236,12 @@ static int regulator_check_voltage(struct regulator_dev *rdev, return 0; } +/* return 0 if the state is valid */ +static int regulator_check_states(suspend_state_t state) +{ + return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE); +} + /* Make sure we select a voltage that suits the needs of all * regulator consumers */ @@ -327,6 +333,24 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, return -EINVAL; } +static inline struct regulator_state * +regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) +{ + if (rdev->constraints == NULL) + return NULL; + + switch (state) { + case PM_SUSPEND_STANDBY: + return &rdev->constraints->state_standby; + case PM_SUSPEND_MEM: + return &rdev->constraints->state_mem; + case PM_SUSPEND_MAX: + return &rdev->constraints->state_disk; + default: + return NULL; + } +} + static ssize_t regulator_uV_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -734,9 +758,14 @@ static int drms_uA_update(struct regulator_dev *rdev) } static int suspend_set_state(struct regulator_dev *rdev, - struct regulator_state *rstate) + suspend_state_t state) { int ret = 0; + struct regulator_state *rstate; + + rstate = regulator_get_suspend_state(rdev, state); + if (rstate == NULL) + return -EINVAL; /* If we have no suspend mode configration don't set anything; * only warn if the driver implements set_suspend_voltage or @@ -779,28 +808,8 @@ static int suspend_set_state(struct regulator_dev *rdev, return ret; } } - return ret; -} - -/* locks held by caller */ -static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) -{ - if (!rdev->constraints) - return -EINVAL; - switch (state) { - case PM_SUSPEND_STANDBY: - return suspend_set_state(rdev, - &rdev->constraints->state_standby); - case PM_SUSPEND_MEM: - return suspend_set_state(rdev, - &rdev->constraints->state_mem); - case PM_SUSPEND_MAX: - return suspend_set_state(rdev, - &rdev->constraints->state_disk); - default: - return -EINVAL; - } + return ret; } static void print_constraints(struct regulator_dev *rdev) @@ -1069,7 +1078,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, /* do we need to setup our suspend state */ if (rdev->constraints->initial_state) { - ret = suspend_prepare(rdev, rdev->constraints->initial_state); + ret = suspend_set_state(rdev, rdev->constraints->initial_state); if (ret < 0) { rdev_err(rdev, "failed to set suspend state\n"); return ret; @@ -2898,6 +2907,32 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, return ret; } +static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, suspend_state_t state) +{ + struct regulator_state *rstate; + int uV, sel; + + rstate = regulator_get_suspend_state(rdev, state); + if (rstate == NULL) + return -EINVAL; + + if (min_uV < rstate->min_uV) + min_uV = rstate->min_uV; + if (max_uV > rstate->max_uV) + max_uV = rstate->max_uV; + + sel = regulator_map_voltage(rdev, min_uV, max_uV); + if (sel < 0) + return sel; + + uV = rdev->desc->ops->list_voltage(rdev, sel); + if (uV >= min_uV && uV <= max_uV) + rstate->uV = uV; + + return 0; +} + static int regulator_set_voltage_unlocked(struct regulator *regulator, int min_uV, int max_uV, suspend_state_t state) @@ -2993,7 +3028,11 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, } } - ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); + if (state == PM_SUSPEND_ON) + ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); + else + ret = _regulator_do_set_suspend_voltage(rdev, min_uV, + max_uV, state); if (ret < 0) goto out2; @@ -3049,6 +3088,89 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) } EXPORT_SYMBOL_GPL(regulator_set_voltage); +static inline int regulator_suspend_toggle(struct regulator_dev *rdev, + suspend_state_t state, bool en) +{ + struct regulator_state *rstate; + + rstate = regulator_get_suspend_state(rdev, state); + if (rstate == NULL) + return -EINVAL; + + if (!rstate->changeable) + return -EPERM; + + rstate->enabled = en; + + return 0; +} + +int regulator_suspend_enable(struct regulator_dev *rdev, + suspend_state_t state) +{ + return regulator_suspend_toggle(rdev, state, true); +} +EXPORT_SYMBOL_GPL(regulator_suspend_enable); + +int regulator_suspend_disable(struct regulator_dev *rdev, + suspend_state_t state) +{ + struct regulator *regulator; + struct regulator_voltage *voltage; + + /* + * if any consumer wants this regulator device keeping on in + * suspend states, don't set it as disabled. + */ + list_for_each_entry(regulator, &rdev->consumer_list, list) { + voltage = ®ulator->voltage[state]; + if (voltage->min_uV || voltage->max_uV) + return 0; + } + + return regulator_suspend_toggle(rdev, state, false); +} +EXPORT_SYMBOL_GPL(regulator_suspend_disable); + +static int _regulator_set_suspend_voltage(struct regulator *regulator, + int min_uV, int max_uV, + suspend_state_t state) +{ + struct regulator_dev *rdev = regulator->rdev; + struct regulator_state *rstate; + + rstate = regulator_get_suspend_state(rdev, state); + if (rstate == NULL) + return -EINVAL; + + if (rstate->min_uV == rstate->max_uV) { + rdev_err(rdev, "The suspend voltage can't be changed!\n"); + return -EPERM; + } + + return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state); +} + +int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, + int max_uV, suspend_state_t state) +{ + int ret = 0; + + /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ + if (regulator_check_states(state) || state == PM_SUSPEND_ON) + return -EINVAL; + + regulator_lock_supply(regulator->rdev); + + ret = _regulator_set_suspend_voltage(regulator, min_uV, + max_uV, state); + + regulator_unlock_supply(regulator->rdev); + + return ret; +} +EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage); + /** * regulator_set_voltage_time - get raise/fall time * @regulator: regulator source @@ -3923,12 +4045,6 @@ static void regulator_dev_release(struct device *dev) kfree(rdev); } -static struct class regulator_class = { - .name = "regulator", - .dev_release = regulator_dev_release, - .dev_groups = regulator_dev_groups, -}; - static void rdev_init_debugfs(struct regulator_dev *rdev) { struct device *parent = rdev->dev.parent; @@ -4179,7 +4295,76 @@ void regulator_unregister(struct regulator_dev *rdev) } EXPORT_SYMBOL_GPL(regulator_unregister); +static int _regulator_suspend_late(struct device *dev, void *data) +{ + struct regulator_dev *rdev = dev_to_rdev(dev); + suspend_state_t *state = data; + int ret; + + mutex_lock(&rdev->mutex); + ret = suspend_set_state(rdev, *state); + mutex_unlock(&rdev->mutex); + return ret; +} + +/** + * regulator_suspend_late - prepare regulators for system wide suspend + * @state: system suspend state + * + * Configure each regulator with it's suspend operating parameters for state. + */ +static int regulator_suspend_late(struct device *dev) +{ + suspend_state_t state = pm_suspend_target_state; + + return class_for_each_device(®ulator_class, NULL, &state, + _regulator_suspend_late); +} +static int _regulator_resume_early(struct device *dev, void *data) +{ + int ret = 0; + struct regulator_dev *rdev = dev_to_rdev(dev); + suspend_state_t *state = data; + struct regulator_state *rstate; + + rstate = regulator_get_suspend_state(rdev, *state); + if (rstate == NULL) + return -EINVAL; + + mutex_lock(&rdev->mutex); + + if (rdev->desc->ops->resume_early && + (rstate->enabled == ENABLE_IN_SUSPEND || + rstate->enabled == DISABLE_IN_SUSPEND)) + ret = rdev->desc->ops->resume_early(rdev); + + mutex_unlock(&rdev->mutex); + + return ret; +} + +static int regulator_resume_early(struct device *dev) +{ + suspend_state_t state = pm_suspend_target_state; + + return class_for_each_device(®ulator_class, NULL, &state, + _regulator_resume_early); +} + +static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { + .suspend_late = regulator_suspend_late, + .resume_early = regulator_resume_early, +}; + +static struct class regulator_class = { + .name = "regulator", + .dev_release = regulator_dev_release, + .dev_groups = regulator_dev_groups, +#ifdef CONFIG_PM_SLEEP + .pm = ®ulator_pm_ops, +#endif +}; /** * regulator_has_full_constraints - the system has fully specified constraints * diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 41dad42..a09ef6c 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -184,9 +184,23 @@ static void of_get_regulation_constraints(struct device_node *np, else suspend_state->enabled = DO_NOTHING_IN_SUSPEND; + if (!of_property_read_u32(np, "regulator-suspend-min-microvolt", + &pval)) + suspend_state->min_uV = pval; + + if (!of_property_read_u32(np, "regulator-suspend-max-microvolt", + &pval)) + suspend_state->max_uV = pval; + if (!of_property_read_u32(suspend_np, "regulator-suspend-microvolt", &pval)) suspend_state->uV = pval; + else /* otherwise use min_uV as default suspend voltage */ + suspend_state->uV = suspend_state->min_uV; + + if (of_property_read_bool(suspend_np, + "regulator-changeable-in-suspend")) + suspend_state->changeable = true; if (i == PM_SUSPEND_MEM) constraints->initial_state = PM_SUSPEND_MEM; diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 94417b4..4c00486 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -214,6 +214,8 @@ struct regulator_ops { /* set regulator suspend operating mode (defined in consumer.h) */ int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode); + int (*resume_early)(struct regulator_dev *rdev); + int (*set_pull_down) (struct regulator_dev *); }; diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index c4a56df..93a0489 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -66,17 +66,24 @@ enum regulator_active_discharge { * state. One of enabled or disabled must be set for the * configuration to be applied. * - * @uV: Operating voltage during suspend. + * @uV: Default operating voltage during suspend, it can be adjusted + * among . + * @min_uV: Minimum suspend voltage may be set. + * @max_uV: Maximum suspend voltage may be set. * @mode: Operating mode during suspend. * @enabled: operations during suspend. * - DO_NOTHING_IN_SUSPEND * - DISABLE_IN_SUSPEND * - ENABLE_IN_SUSPEND + * @changeable: Is this state can be switched between enabled/disabled, */ struct regulator_state { - int uV; /* suspend voltage */ - unsigned int mode; /* suspend regulator operating mode */ + int uV; + int min_uV; + int max_uV; + unsigned int mode; int enabled; + bool changeable; }; /**