msm: rpm-regulator: Allow rpm_vreg_set_voltage voltage switch control
Modify the rpm-regulator driver so that rpm_vreg_set_voltage
supports voltage switch type regulators which do not have a
voltage setting.
For these types of regulators make rpm_vreg_set_voltage calls
map as follows:
1. max_uV > 0 --> vote to enable the voltage switch
2. max_uV == 0 --> vote to disable the voltage switch
This modification is needed so that the acpuclock driver can call
rpm_vreg_set_voltage successfully for a voltage switch on the
APQ8064 platform.
Change-Id: Ibde2ded8fe578cb82e0a3bc28cdf046017583e06
Signed-off-by: David Collins <collinsd@codeaurora.org>
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 946d31b..c472f94 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -268,8 +268,10 @@
if (vreg->part->uV.mask)
uV = GET_PART(vreg, uV);
- else
+ else if (vreg->part->mV.mask)
uV = MILLI_TO_MICRO(GET_PART(vreg, mV));
+ else if (vreg->part->enable_state.mask)
+ uV = GET_PART(vreg, enable_state);
return uV;
}
@@ -278,8 +280,10 @@
{
if (vreg->part->uV.mask)
SET_PART(vreg, uV, uV);
- else
+ else if (vreg->part->mV.mask)
SET_PART(vreg, mV, MICRO_TO_MILLI(uV));
+ else if (vreg->part->enable_state.mask)
+ SET_PART(vreg, enable_state, uV);
}
static int vreg_send_request(struct vreg *vreg, enum rpm_vreg_voter voter,
@@ -380,9 +384,14 @@
if (vreg->part->uV.mask) {
s_val[vreg->part->uV.word] = 0 << vreg->part->uV.shift;
s_mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
+ } else if (vreg->part->mV.mask) {
s_val[vreg->part->mV.word] = 0 << vreg->part->mV.shift;
s_mask[vreg->part->mV.word] = vreg->part->mV.mask;
+ } else if (vreg->part->enable_state.mask) {
+ s_val[vreg->part->enable_state.word]
+ = 0 << vreg->part->enable_state.shift;
+ s_mask[vreg->part->enable_state.word]
+ = vreg->part->enable_state.mask;
}
rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
@@ -421,6 +430,10 @@
*
* Consumers can vote to disable a regulator with this function by passing
* min_uV = 0 and max_uV = 0.
+ *
+ * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
+ * as well. For this type of regulator, max_uV > 0 is treated as an enable
+ * request and max_uV == 0 is treated as a disable request.
*/
int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
int max_uV, int sleep_also)
@@ -450,7 +463,6 @@
}
vreg = &config->vregs[vreg_id];
- range = &vreg->set_points->range[0];
if (!vreg->pdata.sleep_selectable) {
vreg_err(vreg, "regulator is not marked sleep selectable\n");
@@ -458,7 +470,8 @@
}
/* Allow min_uV == max_uV == 0 to represent a disable request. */
- if (min_uV != 0 || max_uV != 0) {
+ if ((min_uV != 0 || max_uV != 0)
+ && (vreg->part->uV.mask || vreg->part->mV.mask)) {
/*
* Check if request voltage is outside of allowed range. The
* regulator core has already checked that constraint range
@@ -477,6 +490,7 @@
return -EINVAL;
}
+ range = &vreg->set_points->range[0];
/* Find the range which uV is inside of. */
for (i = vreg->set_points->count - 1; i > 0; i--) {
if (uV > vreg->set_points->range[i - 1].max_uV) {
@@ -504,10 +518,20 @@
if (vreg->part->uV.mask) {
val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
+ } else if (vreg->part->mV.mask) {
val[vreg->part->mV.word]
= MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
mask[vreg->part->mV.word] = vreg->part->mV.mask;
+ } else if (vreg->part->enable_state.mask) {
+ /*
+ * Translate max_uV > 0 into an enable request for regulator
+ * types which to not support voltage setting, e.g. voltage
+ * switches.
+ */
+ val[vreg->part->enable_state.word]
+ = (max_uV > 0 ? 1 : 0) << vreg->part->enable_state.shift;
+ mask[vreg->part->enable_state.word]
+ = vreg->part->enable_state.mask;
}
rc = vreg_set_noirq(vreg, voter, sleep_also, mask[0], val[0], mask[1],