summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Collins <collinsd@codeaurora.org>2017-04-14 15:34:41 -0700
committerTirupathi Reddy <tirupath@codeaurora.org>2017-06-05 11:38:34 +0530
commit4544adae4c12f1c43b1eb61b398dc8f1a8814303 (patch)
treee5de8018188a15aea7192e908ee8dddab806ff41
parenta62f42964d5606a6ef123f4608f6cb5241598c25 (diff)
regulator: rpm-smd-regulator: add support for load based mode control
Add support to request PWM or AUTO mode for BoB and SMPS type regulators based upon the aggregated consumer load current. This can be used in cases where a consumer needs to force PWM mode operation. CRs-Fixed: 2054771 Change-Id: Iaf4353fb60468c91f958a968d844b3c1c012e54c Signed-off-by: David Collins <collinsd@codeaurora.org> Signed-off-by: Tirupathi Reddy <tirupath@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt6
-rw-r--r--drivers/regulator/rpm-smd-regulator.c59
2 files changed, 62 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt b/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
index 1eb27f4c1c56..559ee5b6fc08 100644
--- a/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
@@ -104,6 +104,12 @@ Optional properties:
parameter. Only one pin may be specified per
regulator. This property only applies to BoB
type regulators.
+- qcom,pwm-threshold-current: Minimum current in mA which requires regulator
+ to be in PWM mode. Load currents below this
+ threshold use AUTO mode. This property only
+ applies to BoB and SMPS type regulators.
+ If this property is not specified, then the
+ hardware default mode will be used all the time.
- qcom,always-send-voltage: Flag which indicates that updates to the
voltage, voltage corner or voltage level set
point should always be sent immediately to the
diff --git a/drivers/regulator/rpm-smd-regulator.c b/drivers/regulator/rpm-smd-regulator.c
index d26fd3bea788..a5dc1b983bcb 100644
--- a/drivers/regulator/rpm-smd-regulator.c
+++ b/drivers/regulator/rpm-smd-regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -207,6 +207,7 @@ struct rpm_regulator {
bool use_pin_ctrl_for_enable;
struct rpm_vreg_request req;
int system_load;
+ int hpm_threshold_current;
int min_uV;
int max_uV;
u32 pin_ctrl_mask[RPM_VREG_PIN_CTRL_STATE_COUNT];
@@ -1030,6 +1031,34 @@ static unsigned int rpm_vreg_get_bob_mode(struct regulator_dev *rdev)
return mode;
}
+static unsigned int rpm_vreg_get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV, int load_uA)
+{
+ struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+ u32 mode = REGULATOR_MODE_NORMAL;
+
+ if (reg->hpm_threshold_current > 0) {
+ if (load_uA >= reg->hpm_threshold_current) {
+ /* PWM mode */
+ mode = (reg->rpm_vreg->regulator_type
+ == RPM_REGULATOR_TYPE_BOB)
+ ? REGULATOR_MODE_FAST
+ : REGULATOR_MODE_NORMAL;
+ } else {
+ /* AUTO mode */
+ mode = (reg->rpm_vreg->regulator_type
+ == RPM_REGULATOR_TYPE_BOB)
+ ? REGULATOR_MODE_NORMAL
+ : REGULATOR_MODE_IDLE;
+ }
+ } else {
+ /* Default to the current mode if no threshold is present. */
+ mode = reg->rdesc.ops->get_mode(rdev);
+ }
+
+ return mode;
+}
+
static int rpm_vreg_enable_time(struct regulator_dev *rdev)
{
struct rpm_regulator *reg = rdev_get_drvdata(rdev);
@@ -1402,6 +1431,18 @@ static struct regulator_ops smps_ops = {
.enable_time = rpm_vreg_enable_time,
};
+static struct regulator_ops smps_optimum_mode_ops = {
+ .enable = rpm_vreg_enable,
+ .disable = rpm_vreg_disable,
+ .is_enabled = rpm_vreg_is_enabled,
+ .set_voltage = rpm_vreg_set_voltage,
+ .get_voltage = rpm_vreg_get_voltage,
+ .set_mode = rpm_vreg_set_mode,
+ .get_mode = rpm_vreg_get_mode,
+ .get_optimum_mode = rpm_vreg_get_optimum_mode,
+ .enable_time = rpm_vreg_enable_time,
+};
+
static struct regulator_ops switch_ops = {
.enable = rpm_vreg_enable,
.disable = rpm_vreg_disable,
@@ -1426,6 +1467,7 @@ static struct regulator_ops bob_ops = {
.get_voltage = rpm_vreg_get_voltage,
.set_mode = rpm_vreg_set_bob_mode,
.get_mode = rpm_vreg_get_bob_mode,
+ .get_optimum_mode = rpm_vreg_get_optimum_mode,
.enable_time = rpm_vreg_enable_time,
};
@@ -1676,6 +1718,12 @@ static int rpm_vreg_device_probe(struct platform_device *pdev)
if (of_get_property(node, "parent-supply", NULL))
init_data->supply_regulator = "parent";
+ of_property_read_u32(node, "qcom,pwm-threshold-current",
+ &reg->hpm_threshold_current);
+ if (reg->hpm_threshold_current > 0
+ && regulator_type == RPM_REGULATOR_TYPE_SMPS)
+ reg->rdesc.ops = &smps_optimum_mode_ops;
+
/*
* Fill in ops and mode masks based on callbacks specified for
* this type of regulator.
@@ -1689,8 +1737,13 @@ static int rpm_vreg_device_probe(struct platform_device *pdev)
if (reg->rdesc.ops->get_mode) {
init_data->constraints.valid_ops_mask
|= REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_DRMS;
- init_data->constraints.valid_modes_mask
- |= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE;
+
+ if (regulator_type == RPM_REGULATOR_TYPE_BOB)
+ init_data->constraints.valid_modes_mask
+ = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL;
+ else
+ init_data->constraints.valid_modes_mask
+ |= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE;
}
reg->rdesc.name = init_data->constraints.name;