Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 21db945a authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "regulator: rpm-smd-regulator: don't wait for ACK when lowering power state"

parents ef8777aa b9f3ad37
Loading
Loading
Loading
Loading
+40 −6
Original line number Diff line number Diff line
@@ -36,6 +36,10 @@ Optional properties:
			consumers on the application processor. If this flag
			is specified, then voltage and current updates are
			only sent to the RPM if the regulator is enabled.
- qcom,always-wait-for-ack:   Flag which indicates that the application
			processor must wait for an ACK or a NACK from the RPM
			for every request sent for this regulator including
			those which are for a strictly lower power state.

[Second Level Nodes]

@@ -76,12 +80,23 @@ Optional properties:
				qcom,use-voltage-floor-corner are mutually
				exclusive.  Only one may be specified for a
				given regulator.
- qcom,always-send-voltage:    Flag which indicates that updates to the voltage
				or voltage corner set point should always be
				sent immediately to the RPM.  If this flag is
				not specified, then voltage set point updates
				are only sent if the given regulator has also
				been enabled by a Linux consumer.
- qcom,use-voltage-level:      Flag that signifies if regulator_set_voltage
				calls should modify the level parameter instead
				of the voltage parameter.
- qcom,use-voltage-floor-level:   Flag that signifies if regulator_set_voltage
				calls should modify the floor level parameter
				instead of the voltage parameter.
				The properties qcom,use-voltage-level and
				qcom,use-voltage-floor-level are mutually
				exclusive.  Only one may be specified for a
				given regulator.
- 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
				RPM. If this flag is not specified, then
				voltage set point updates are only sent if the
				given regulator has also been enabled by a
				Linux consumer.
- qcom,always-send-current:    Flag which indicates that updates to the load
				current should always be sent immediately to the
				RPM.  If this flag is not specified, then load
@@ -195,6 +210,25 @@ RPM in regulator requests.
				processor in the system is awake.  This property
				supports the same values as
				qcom,init-voltage-corner.
- qcom,init-voltage-level:     Performance level to use in order to determine
				voltage set point. The meaning of level
				values is set by the RPM. It is possible that
				different regulators on a given platform or
				similar regulators on different platforms will
				utilize different level values. These are
				level values supported on MSM8952 for PMIC
				PM8952 SMPS 2 (VDD_Dig); nominal voltages for
				these level are also shown:
					16  = Retention    (0.5000 V)
					128 = SVS          (1.0500 V)
					192 = SVS+         (1.1550 V)
					256 = Normal       (1.2250 V)
					320 = Normal+      (1.2875 V)
					384 = Turbo        (1.3500 V)
- qcom,init-voltage-floor-level:   Minimum performance level to use if any
				processor in the system is awake. This property
				supports the same values as
				qcom,init-voltage-level.

All properties specified within the core regulator framework can also be used in
second level nodes.  These bindings can be found in:
+324 −39
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, 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
@@ -69,6 +69,8 @@ enum rpm_regulator_param_index {
	RPM_REGULATOR_PARAM_CORNER,
	RPM_REGULATOR_PARAM_BYPASS,
	RPM_REGULATOR_PARAM_FLOOR_CORNER,
	RPM_REGULATOR_PARAM_LEVEL,
	RPM_REGULATOR_PARAM_FLOOR_LEVEL,
	RPM_REGULATOR_PARAM_MAX,
};

@@ -126,6 +128,8 @@ static struct rpm_regulator_param params[RPM_REGULATOR_PARAM_MAX] = {
	PARAM(CORNER,          1,  1,  0,  0, "corn", 0, 6,          "qcom,init-voltage-corner"),
	PARAM(BYPASS,          1,  0,  0,  0, "bypa", 0, 1,          "qcom,init-disallow-bypass"),
	PARAM(FLOOR_CORNER,    1,  1,  0,  0, "vfc",  0, 6,          "qcom,init-voltage-floor-corner"),
	PARAM(LEVEL,           1,  1,  0,  0, "vlvl", 0, 0xFFFF,     "qcom,init-voltage-level"),
	PARAM(FLOOR_LEVEL,     1,  1,  0,  0, "vfl",  0, 0xFFFF,     "qcom,init-voltage-floor-level"),
};

struct rpm_regulator_mode_map {
@@ -167,6 +171,9 @@ struct rpm_vreg {
	struct mutex		mlock;
	unsigned long		flags;
	bool			sleep_request_sent;
	bool			wait_for_ack_active;
	bool			wait_for_ack_sleep;
	bool			always_wait_for_ack;
	bool			apps_only;
	struct msm_rpm_request	*handle_active;
	struct msm_rpm_request	*handle_sleep;
@@ -258,6 +265,58 @@ static inline bool rpm_vreg_shared_active_or_sleep_enabled_valid
					& BIT(RPM_REGULATOR_PARAM_ENABLE)));
}

static const u32 power_level_params =
	BIT(RPM_REGULATOR_PARAM_ENABLE) |
	BIT(RPM_REGULATOR_PARAM_VOLTAGE) |
	BIT(RPM_REGULATOR_PARAM_CURRENT) |
	BIT(RPM_REGULATOR_PARAM_CORNER) |
	BIT(RPM_REGULATOR_PARAM_BYPASS) |
	BIT(RPM_REGULATOR_PARAM_FLOOR_CORNER) |
	BIT(RPM_REGULATOR_PARAM_LEVEL) |
	BIT(RPM_REGULATOR_PARAM_FLOOR_LEVEL);

static bool rpm_vreg_ack_required(struct rpm_vreg *rpm_vreg, u32 set,
				const u32 *prev_param, const u32 *param,
				u32 prev_valid, u32 modified)
{
	u32 mask;
	int i;

	if (rpm_vreg->always_wait_for_ack
	    || (set == RPM_SET_ACTIVE && rpm_vreg->wait_for_ack_active)
	    || (set == RPM_SET_SLEEP && rpm_vreg->wait_for_ack_sleep))
		return true;

	for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
		mask = BIT(i);
		if (modified & mask) {
			if ((prev_valid & mask) && (power_level_params & mask)
			    && (param[i] <= prev_param[i]))
				continue;
			else
				return true;
		}
	}

	return false;
}

static void rpm_vreg_check_param_max(struct rpm_regulator *regulator, int index,
					u32 new_max)
{
	struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;

	if (regulator->set_active
	    && (rpm_vreg->aggr_req_active.valid & BIT(index))
	    && rpm_vreg->aggr_req_active.param[index] > new_max)
		rpm_vreg->wait_for_ack_active = true;

	if (regulator->set_sleep
	    && (rpm_vreg->aggr_req_sleep.valid & BIT(index))
	    && rpm_vreg->aggr_req_sleep.param[index] > new_max)
		rpm_vreg->wait_for_ack_sleep = true;
}

/*
 * This is used when voting for LPM or HPM by subtracting or adding to the
 * hpm_min_load of a regulator.  It has units of uA.
@@ -413,27 +472,37 @@ static int rpm_vreg_add_modified_requests(struct rpm_regulator *regulator,
	return rc;
}

static int rpm_vreg_send_request(struct rpm_regulator *regulator, u32 set)
static int rpm_vreg_send_request(struct rpm_regulator *regulator, u32 set,
				bool wait_for_ack)
{
	struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
	struct msm_rpm_request *handle
		= (set == RPM_SET_ACTIVE ? rpm_vreg->handle_active
					: rpm_vreg->handle_sleep);
	u32 msg_id;
	int rc;

	if (rpm_vreg->allow_atomic)
		rc = msm_rpm_wait_for_ack_noirq(msm_rpm_send_request_noirq(
						  handle));
	else
		rc = msm_rpm_wait_for_ack(msm_rpm_send_request(handle));
	rc = unlikely(rpm_vreg->allow_atomic) ?
	      msm_rpm_send_request_noirq(handle) : msm_rpm_send_request(handle);
	if (rc < 0)
		goto fail;

	if (rc)
		vreg_err(regulator,
			"msm rpm send failed: %s %u; set=%s, rc=%d\n",
			rpm_vreg->resource_name,
			rpm_vreg->resource_id,
			(set == RPM_SET_ACTIVE ? "act" : "slp"), rc);
	msg_id = rc;

	if (wait_for_ack) {
		rc = unlikely(rpm_vreg->allow_atomic) ?
			msm_rpm_wait_for_ack_noirq(msg_id) :
			msm_rpm_wait_for_ack(msg_id);
		if (rc < 0)
			goto fail;
	}

	return 0;

fail:
	vreg_err(regulator, "msm rpm send failed: %s %u; set=%s, rc=%d\n",
		rpm_vreg->resource_name, rpm_vreg->resource_id,
		(set == RPM_SET_ACTIVE ? "act" : "slp"), rc);
	return rc;
}

@@ -483,6 +552,8 @@ static void rpm_vreg_aggregate_params(u32 *param_aggr, const u32 *param_reg)
	RPM_VREG_AGGR_MAX(CORNER, param_aggr, param_reg);
	RPM_VREG_AGGR_MAX(BYPASS, param_aggr, param_reg);
	RPM_VREG_AGGR_MAX(FLOOR_CORNER, param_aggr, param_reg);
	RPM_VREG_AGGR_MAX(LEVEL, param_aggr, param_reg);
	RPM_VREG_AGGR_MAX(FLOOR_LEVEL, param_aggr, param_reg);
}

static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
@@ -495,6 +566,7 @@ static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
	bool sleep_set_differs = false;
	bool send_active = false;
	bool send_sleep = false;
	bool wait_for_ack;
	int rc = 0;
	int i;

@@ -566,10 +638,17 @@ static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)

	/* Send active set request to the RPM if it contains new KVPs. */
	if (send_active) {
		rc = rpm_vreg_send_request(regulator, RPM_SET_ACTIVE);
		wait_for_ack = rpm_vreg_ack_required(rpm_vreg, RPM_SET_ACTIVE,
					rpm_vreg->aggr_req_active.param,
					param_active,
					rpm_vreg->aggr_req_active.valid,
					modified_active);
		rc = rpm_vreg_send_request(regulator, RPM_SET_ACTIVE,
						wait_for_ack);
		if (rc)
			return rc;
		rpm_vreg->aggr_req_active.valid |= modified_active;
		rpm_vreg->wait_for_ack_active = false;
	}
	/* Store the results of the aggregation. */
	rpm_vreg->aggr_req_active.modified = modified_active;
@@ -583,12 +662,19 @@ static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)

	/* Send sleep set request to the RPM if it contains new KVPs. */
	if (send_sleep) {
		rc = rpm_vreg_send_request(regulator, RPM_SET_SLEEP);
		wait_for_ack = rpm_vreg_ack_required(rpm_vreg, RPM_SET_SLEEP,
					rpm_vreg->aggr_req_sleep.param,
					param_sleep,
					rpm_vreg->aggr_req_sleep.valid,
					modified_sleep);
		rc = rpm_vreg_send_request(regulator, RPM_SET_SLEEP,
						wait_for_ack);
		if (rc)
			return rc;
		else
			rpm_vreg->sleep_request_sent = true;
		rpm_vreg->aggr_req_sleep.valid |= modified_sleep;
		rpm_vreg->wait_for_ack_sleep = false;
	}
	/* Store the results of the aggregation. */
	rpm_vreg->aggr_req_sleep.modified = modified_sleep;
@@ -705,6 +791,8 @@ static int rpm_vreg_set_voltage(struct regulator_dev *rdev, int min_uV,
	prev_voltage = reg->req.param[RPM_REGULATOR_PARAM_VOLTAGE];
	RPM_VREG_SET_PARAM(reg, VOLTAGE, min_uV);

	rpm_vreg_check_param_max(reg, RPM_REGULATOR_PARAM_VOLTAGE, max_uV);

	/*
	 * Only send a new voltage if the regulator is currently enabled or
	 * if the regulator has been configured to always send voltage updates.
@@ -764,6 +852,9 @@ static int rpm_vreg_set_voltage_corner(struct regulator_dev *rdev, int min_uV,
	prev_corner = reg->req.param[RPM_REGULATOR_PARAM_CORNER];
	RPM_VREG_SET_PARAM(reg, CORNER, corner);

	rpm_vreg_check_param_max(reg, RPM_REGULATOR_PARAM_CORNER,
				max_uV - RPM_REGULATOR_CORNER_NONE);

	/*
	 * Only send a new voltage corner if the regulator is currently enabled
	 * or if the regulator has been configured to always send voltage
@@ -820,6 +911,9 @@ static int rpm_vreg_set_voltage_floor_corner(struct regulator_dev *rdev,
	prev_corner = reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER];
	RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, corner);

	rpm_vreg_check_param_max(reg, RPM_REGULATOR_PARAM_FLOOR_CORNER,
				max_uV - RPM_REGULATOR_CORNER_NONE);

	/*
	 * Only send a new voltage floor corner if the regulator is currently
	 * enabled or if the regulator has been configured to always send
@@ -848,6 +942,108 @@ static int rpm_vreg_get_voltage_floor_corner(struct regulator_dev *rdev)
		+ RPM_REGULATOR_CORNER_NONE;
}

static int rpm_vreg_set_voltage_level(struct regulator_dev *rdev, int min_uV,
				int max_uV, unsigned *selector)
{
	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
	int rc = 0;
	int level;
	u32 prev_level;

	level = min_uV;
	if (level < params[RPM_REGULATOR_PARAM_LEVEL].min
	    || level > params[RPM_REGULATOR_PARAM_LEVEL].max) {
		vreg_err(reg, "level=%d is not within allowed range: [%u, %u]\n",
			level, params[RPM_REGULATOR_PARAM_LEVEL].min,
			params[RPM_REGULATOR_PARAM_LEVEL].max);
		return -EINVAL;
	}

	rpm_vreg_lock(reg->rpm_vreg);

	prev_level = reg->req.param[RPM_REGULATOR_PARAM_LEVEL];
	RPM_VREG_SET_PARAM(reg, LEVEL, level);

	rpm_vreg_check_param_max(reg, RPM_REGULATOR_PARAM_LEVEL, max_uV);

	/*
	 * Only send a new voltage level if the regulator is currently enabled
	 * or if the regulator has been configured to always send voltage
	 * updates.
	 */
	if (reg->always_send_voltage
	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
	    || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
		rc = rpm_vreg_aggregate_requests(reg);

	if (rc) {
		vreg_err(reg, "set voltage level failed, rc=%d", rc);
		RPM_VREG_SET_PARAM(reg, LEVEL, prev_level);
	}

	rpm_vreg_unlock(reg->rpm_vreg);

	return rc;
}

static int rpm_vreg_get_voltage_level(struct regulator_dev *rdev)
{
	struct rpm_regulator *reg = rdev_get_drvdata(rdev);

	return reg->req.param[RPM_REGULATOR_PARAM_LEVEL];
}

static int rpm_vreg_set_voltage_floor_level(struct regulator_dev *rdev,
				int min_uV, int max_uV, unsigned *selector)
{
	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
	int rc = 0;
	int level;
	u32 prev_level;

	level = min_uV;
	if (level < params[RPM_REGULATOR_PARAM_FLOOR_LEVEL].min
	    || level > params[RPM_REGULATOR_PARAM_FLOOR_LEVEL].max) {
		vreg_err(reg, "level=%d is not within allowed range: [%u, %u]\n",
			level, params[RPM_REGULATOR_PARAM_FLOOR_LEVEL].min,
			params[RPM_REGULATOR_PARAM_FLOOR_LEVEL].max);
		return -EINVAL;
	}

	rpm_vreg_lock(reg->rpm_vreg);

	prev_level = reg->req.param[RPM_REGULATOR_PARAM_FLOOR_LEVEL];
	RPM_VREG_SET_PARAM(reg, FLOOR_LEVEL, level);

	rpm_vreg_check_param_max(reg, RPM_REGULATOR_PARAM_FLOOR_LEVEL, max_uV);

	/*
	 * Only send a new voltage floor level if the regulator is currently
	 * enabled or if the regulator has been configured to always send
	 * voltage updates.
	 */
	if (reg->always_send_voltage
	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
	    || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
		rc = rpm_vreg_aggregate_requests(reg);

	if (rc) {
		vreg_err(reg, "set voltage floor level failed, rc=%d", rc);
		RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, prev_level);
	}

	rpm_vreg_unlock(reg->rpm_vreg);

	return rc;
}

static int rpm_vreg_get_voltage_floor_level(struct regulator_dev *rdev)
{
	struct rpm_regulator *reg = rdev_get_drvdata(rdev);

	return reg->req.param[RPM_REGULATOR_PARAM_FLOOR_LEVEL];
}

static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
@@ -1309,6 +1505,30 @@ static struct regulator_ops ldo_floor_corner_ops = {
	.enable_time		= rpm_vreg_enable_time,
};

static struct regulator_ops ldo_level_ops = {
	.enable			= rpm_vreg_enable,
	.disable		= rpm_vreg_disable,
	.is_enabled		= rpm_vreg_is_enabled,
	.set_voltage		= rpm_vreg_set_voltage_level,
	.get_voltage		= rpm_vreg_get_voltage_level,
	.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 ldo_floor_level_ops = {
	.enable			= rpm_vreg_enable,
	.disable		= rpm_vreg_disable,
	.is_enabled		= rpm_vreg_is_enabled,
	.set_voltage		= rpm_vreg_set_voltage_floor_level,
	.get_voltage		= rpm_vreg_get_voltage_floor_level,
	.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 smps_ops = {
	.enable			= rpm_vreg_enable,
	.disable		= rpm_vreg_disable,
@@ -1345,6 +1565,30 @@ static struct regulator_ops smps_floor_corner_ops = {
	.enable_time		= rpm_vreg_enable_time,
};

static struct regulator_ops smps_level_ops = {
	.enable			= rpm_vreg_enable,
	.disable		= rpm_vreg_disable,
	.is_enabled		= rpm_vreg_is_enabled,
	.set_voltage		= rpm_vreg_set_voltage_level,
	.get_voltage		= rpm_vreg_get_voltage_level,
	.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 smps_floor_level_ops = {
	.enable			= rpm_vreg_enable,
	.disable		= rpm_vreg_disable,
	.is_enabled		= rpm_vreg_is_enabled,
	.set_voltage		= rpm_vreg_set_voltage_floor_level,
	.get_voltage		= rpm_vreg_get_voltage_floor_level,
	.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,
@@ -1429,6 +1673,66 @@ static int rpm_vreg_resource_remove(struct platform_device *pdev)
	return 0;
}

/*
 * Switch regulator ops if one of the following properties is present
 * for the device node (SMPS and LDO only):
 * use corner ops if 'qcom,use-voltage-corner' is present
 * use floor corner ops if 'qcom,use-voltage-floor-corner' is present
 * use level ops if 'qcom,use-voltage-level' present
 * use floor level ops if 'qcom,use-voltage-floor-level' is present
 */
static int rpm_vreg_device_set_regulator_ops(struct device *dev,
					struct rpm_regulator *reg, int type)
{
	bool choosen = false;
	struct device_node *node = dev->of_node;

	reg->rdesc.ops = vreg_ops[type];

	if ((type != RPM_REGULATOR_TYPE_SMPS) &&
			(type != RPM_REGULATOR_TYPE_LDO))
		return 0;

	if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
		reg->rdesc.ops = (type == RPM_REGULATOR_TYPE_SMPS) ?
					&smps_corner_ops : &ldo_corner_ops;
		choosen = true;
	}

	if (of_property_read_bool(node, "qcom,use-voltage-floor-corner")) {
		if (choosen)
			goto invalid;

		reg->rdesc.ops = (type == RPM_REGULATOR_TYPE_SMPS) ?
				&smps_floor_corner_ops : &ldo_floor_corner_ops;
		choosen = true;
	}

	if (of_property_read_bool(node, "qcom,use-voltage-level")) {
		if (choosen)
			goto invalid;

		reg->rdesc.ops = (type == RPM_REGULATOR_TYPE_SMPS) ?
					&smps_level_ops : &ldo_level_ops;
		choosen = true;
	}

	if (of_property_read_bool(node, "qcom,use-voltage-floor-level")) {
		if (choosen)
			goto invalid;

		reg->rdesc.ops = (type == RPM_REGULATOR_TYPE_SMPS) ?
				&smps_floor_level_ops : &ldo_floor_level_ops;
	}

	return 0;

invalid:
	dev_err(dev, "%s: invalid properties: only one of qcom,use-voltage-corner, qcom,use-voltage-floor-corner, qcom,use-voltage-level, or qcom,use-voltage-floor-level may be specified\n",
			__func__);
	return -EINVAL;
}

/*
 * This probe is called for child rpm-regulator devices which have
 * properties which are required to configure individual regulator
@@ -1472,33 +1776,12 @@ static int rpm_vreg_device_probe(struct platform_device *pdev)

	regulator_type		= rpm_vreg->regulator_type;
	reg->rpm_vreg		= rpm_vreg;
	reg->rdesc.ops		= vreg_ops[regulator_type];
	reg->rdesc.owner	= THIS_MODULE;
	reg->rdesc.type		= REGULATOR_VOLTAGE;

	/*
	 * Switch to voltage corner regulator ops if qcom,use-voltage-corner
	 * is specified in the device node (SMPS and LDO only).
	 */
	if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
		if (of_property_read_bool(node,
				"qcom,use-voltage-floor-corner")) {
			dev_err(dev, "%s: invalid properties: both qcom,use-voltage-corner and qcom,use-voltage-floor-corner specified\n",
				__func__);
	rc = rpm_vreg_device_set_regulator_ops(dev, reg, regulator_type);
	if (rc)
		goto fail_free_reg;
		}

		if (regulator_type == RPM_REGULATOR_TYPE_SMPS)
			reg->rdesc.ops = &smps_corner_ops;
		else if (regulator_type == RPM_REGULATOR_TYPE_LDO)
			reg->rdesc.ops = &ldo_corner_ops;
	} else if (of_property_read_bool(node,
			"qcom,use-voltage-floor-corner")) {
		if (regulator_type == RPM_REGULATOR_TYPE_SMPS)
			reg->rdesc.ops = &smps_floor_corner_ops;
		else if (regulator_type == RPM_REGULATOR_TYPE_LDO)
			reg->rdesc.ops = &ldo_floor_corner_ops;
	}

	reg->always_send_voltage
		= of_property_read_bool(node, "qcom,always-send-voltage");
@@ -1704,6 +1987,8 @@ static int rpm_vreg_resource_probe(struct platform_device *pdev)
	of_property_read_u32(node, "qcom,hpm-min-load",
		&rpm_vreg->hpm_min_load);
	rpm_vreg->apps_only = of_property_read_bool(node, "qcom,apps-only");
	rpm_vreg->always_wait_for_ack
		= of_property_read_bool(node, "qcom,always-wait-for-ack");

	rpm_vreg->handle_active = msm_rpm_create_request(RPM_SET_ACTIVE,
		resource_type, rpm_vreg->resource_id, RPM_REGULATOR_PARAM_MAX);
+27 −0
Original line number Diff line number Diff line
/* Copyright (c) 2015, 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef __QCOM_RPM_SMD_REGULATOR_H
#define __QCOM_RPM_SMD_REGULATOR_H

#define RPM_SMD_REGULATOR_LEVEL_NONE		0
#define RPM_SMD_REGULATOR_LEVEL_RETENTION	16
#define RPM_SMD_REGULATOR_LEVEL_MIN_SVS		48
#define RPM_SMD_REGULATOR_LEVEL_LOW_SVS		64
#define RPM_SMD_REGULATOR_LEVEL_SVS		128
#define RPM_SMD_REGULATOR_LEVEL_SVS_PLUS	192
#define RPM_SMD_REGULATOR_LEVEL_NOM		256
#define RPM_SMD_REGULATOR_LEVEL_NOM_PLUS	320
#define RPM_SMD_REGULATOR_LEVEL_TURBO		384
#define RPM_SMD_REGULATOR_LEVEL_BINNING		512

#endif
+24 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2013, 2015 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
@@ -38,6 +38,29 @@ enum rpm_regulator_voltage_corner {
	RPM_REGULATOR_CORNER_SUPER_TURBO,
};

/**
 * enum rpm_regulator_voltage_level - possible voltage level values
 *
 * These should be used in regulator_set_voltage() and
 * rpm_regulator_set_voltage() calls for level type regulators as if they had
 * units of uV.
 *
 * Note: the meaning of level values is set by the RPM.
 */
enum rpm_regulator_voltage_level {
	RPM_REGULATOR_LEVEL_NONE	= 0,
	RPM_REGULATOR_LEVEL_RETENTION	= 16,
	RPM_REGULATOR_LEVEL_MIN_SVS	= 48,
	RPM_REGULATOR_LEVEL_LOW_SVS	= 64,
	RPM_REGULATOR_LEVEL_SVS		= 128,
	RPM_REGULATOR_LEVEL_SVS_PLUS	= 192,
	RPM_REGULATOR_LEVEL_NOM		= 256,
	RPM_REGULATOR_LEVEL_NOM_PLUS	= 320,
	RPM_REGULATOR_LEVEL_TURBO	= 384,
	RPM_REGULATOR_LEVEL_BINNING	= 512,
	RPM_REGULATOR_LEVEL_MAX		= 65535,
};

/**
 * enum rpm_regulator_mode - control mode for LDO or SMPS type regulators
 * %RPM_REGULATOR_MODE_AUTO:	For SMPS type regulators, use SMPS auto mode so