msm: acpuclock-9615: Add voltage scaling support.
Scaling CPU and memory voltages along with the CPU's clock.
Change-Id: Ib5f0cf406e28335efaef031eb466c7a4b8f5efa4
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
diff --git a/arch/arm/mach-msm/acpuclock-9615.c b/arch/arm/mach-msm/acpuclock-9615.c
index 924a46a..ebc7f1b 100644
--- a/arch/arm/mach-msm/acpuclock-9615.c
+++ b/arch/arm/mach-msm/acpuclock-9615.c
@@ -27,6 +27,7 @@
#include <mach/board.h>
#include <mach/msm_iomap.h>
+#include <mach/rpm-regulator.h>
#include "acpuclock.h"
@@ -36,6 +37,9 @@
#define REG_CLKDIV_1 (MSM_APCS_GLB_BASE + 0x14)
#define REG_CLKOUTSEL (MSM_APCS_GLB_BASE + 0x18)
+#define MAX_VDD_CPU 1150000
+#define MAX_VDD_MEM 1150000
+
enum clk_src {
SRC_CXO,
SRC_PLL0,
@@ -62,6 +66,8 @@
int src;
unsigned int src_sel;
unsigned int src_div;
+ unsigned int vdd_cpu;
+ unsigned int vdd_mem;
};
struct acpuclk_state {
@@ -74,11 +80,11 @@
};
static struct clkctl_acpu_speed acpu_freq_tbl[] = {
- { 0, 19200, SRC_CXO, 0, 0 },
- { 1, 138000, SRC_PLL0, 6, 1 },
- { 1, 276000, SRC_PLL0, 6, 0 },
- { 1, 384000, SRC_PLL8, 3, 0 },
- { 1, 440000, SRC_PLL9, 2, 0 },
+ { 0, 19200, SRC_CXO, 0, 0, 950000, 1050000 },
+ { 1, 138000, SRC_PLL0, 6, 1, 950000, 1050000 },
+ { 1, 276000, SRC_PLL0, 6, 0, 1050000, 1050000 },
+ { 1, 384000, SRC_PLL8, 3, 0, 1150000, 1150000 },
+ { 1, 440000, SRC_PLL9, 2, 0, 1150000, 1150000 },
{ 0 }
};
@@ -98,6 +104,53 @@
udelay(1);
}
+/* Apply any per-cpu voltage increases. */
+static int increase_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
+{
+ int rc = 0;
+
+ /*
+ * Increase vdd_mem active-set before vdd_cpu.
+ * vdd_mem should be >= vdd_cpu.
+ */
+ rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_L9, RPM_VREG_VOTER1,
+ vdd_mem, MAX_VDD_MEM, 0);
+ if (rc) {
+ pr_err("vdd_mem increase failed (%d)\n", rc);
+ return rc;
+ }
+
+ rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_S1, RPM_VREG_VOTER1,
+ vdd_cpu, MAX_VDD_CPU, 0);
+ if (rc)
+ pr_err("vdd_cpu increase failed (%d)\n", rc);
+
+ return rc;
+}
+
+/* Apply any per-cpu voltage decreases. */
+static void decrease_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
+{
+ int ret;
+
+ /* Update CPU voltage. */
+ ret = rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_S1, RPM_VREG_VOTER1,
+ vdd_cpu, MAX_VDD_CPU, 0);
+ if (ret) {
+ pr_err("vdd_cpu decrease failed (%d)\n", ret);
+ return;
+ }
+
+ /*
+ * Decrease vdd_mem active-set after vdd_cpu.
+ * vdd_mem should be >= vdd_cpu.
+ */
+ ret = rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_L9, RPM_VREG_VOTER1,
+ vdd_mem, MAX_VDD_MEM, 0);
+ if (ret)
+ pr_err("vdd_mem decrease failed (%d)\n", ret);
+}
+
static int acpuclk_9615_set_rate(int cpu, unsigned long rate,
enum setrate_reason reason)
{
@@ -122,6 +175,14 @@
goto out;
}
+ /* Increase VDD levels if needed. */
+ if ((reason == SETRATE_CPUFREQ || reason == SETRATE_INIT)
+ && (tgt_s->khz > strt_s->khz)) {
+ rc = increase_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
+ if (rc)
+ goto out;
+ }
+
pr_debug("Switching from CPU rate %u KHz -> %u KHz\n",
strt_s->khz, tgt_s->khz);
@@ -133,6 +194,14 @@
drv_state.current_speed = tgt_s;
pr_debug("CPU speed change complete\n");
+ /* Nothing else to do for SWFI or power-collapse. */
+ if (reason == SETRATE_SWFI || reason == SETRATE_PC)
+ goto out;
+
+ /* Drop VDD levels if we can. */
+ if (tgt_s->khz < strt_s->khz)
+ decrease_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
+
out:
if (reason == SETRATE_CPUFREQ)
mutex_unlock(&drv_state.lock);