Merge "msm: clock: Move regulator API calls into clock framework"
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index cc478da..a690033 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -169,22 +169,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -2760,19 +2752,12 @@
VDD_SR2_PLL_NUM
};
-static struct regulator *vdd_sr2_reg;
-static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
-{
- if (level == VDD_SR2_PLL_ON) {
- return regulator_set_voltage(vdd_sr2_reg, 1800000,
- 1800000);
- } else {
- return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
- }
-}
+static const int *vdd_sr2_levels[] = {
+ [VDD_SR2_PLL_OFF] = VDD_UV(0),
+ [VDD_SR2_PLL_ON] = VDD_UV(1800000),
+};
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
- VDD_SR2_PLL_NUM);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1, vdd_sr2_levels);
static struct pll_freq_tbl apcs_pll_freq[] = {
F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -3511,23 +3496,23 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8226: Unable to get the vdd_dig regulator!");
- vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
- if (IS_ERR(vdd_dig_reg))
+ vdd_sr2_pll.regulator[0] = regulator_get(NULL, "vdd_sr2_pll");
+ if (IS_ERR(vdd_sr2_pll.regulator[0]))
panic("clock-8226: Unable to get the sr2_pll regulator!");
/*
* These regulators are used at boot. Ensure they stay on
* while the clock framework comes online.
*/
- regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
- regulator_enable(vdd_sr2_reg);
+ regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+ regulator_enable(vdd_sr2_pll.regulator[0]);
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
/*
* Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index c517c10..930f9e3 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -445,22 +445,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -550,20 +542,13 @@
VDD_SR2_PLL_NUM
};
-static struct regulator *vdd_sr2_reg;
+static const int *vdd_sr2_pll_levels[] = {
+ [VDD_SR2_PLL_OFF] = VDD_UV(0),
+ [VDD_SR2_PLL_ON] = VDD_UV(1800000),
+};
-static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
-{
- if (level == VDD_SR2_PLL_ON) {
- return regulator_set_voltage(vdd_sr2_reg, 1800000,
- 1800000);
- } else {
- return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
- }
-}
-
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
- VDD_SR2_PLL_NUM);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1,
+ vdd_sr2_pll_levels);
static struct pll_freq_tbl apcs_pll_freq[] = {
F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -3546,16 +3531,16 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8610: Unable to get the vdd_dig regulator!");
- vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
- if (IS_ERR(vdd_sr2_reg))
+ vdd_sr2_pll.regulator[0] = regulator_get(NULL, "vdd_sr2_pll");
+ if (IS_ERR(vdd_sr2_pll.regulator[0]))
panic("clock-8610: Unable to get the vdd_sr2_pll regulator!");
- regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
- regulator_enable(vdd_sr2_reg);
+ regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+ regulator_enable(vdd_sr2_pll.regulator[0]);
/*
* TODO: Set a voltage and enable vdd_dig, leaving the voltage high
@@ -3564,7 +3549,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e9824a6..e040d7f 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -638,22 +638,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -5490,8 +5482,8 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8974: Unable to get the vdd_dig regulator!");
/*
@@ -5501,7 +5493,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
@@ -5556,8 +5548,8 @@
sdcc3_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
sdcc4_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8974: Unable to get the vdd_dig regulator!");
/*
@@ -5567,7 +5559,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
}
struct clock_init_data msm8974_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index cd06bb8..d8e4ed5 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -278,22 +278,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
/* TODO: Needs to confirm the below values */
#define RPM_MISC_CLK_TYPE 0x306b6c63
@@ -2062,12 +2054,12 @@
clk_ops_local_pll.enable = sr_pll_clk_enable_9625;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-9625: Unable to get the vdd_dig regulator!");
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index e0ee084..ecd25fc 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/list.h>
+#include <linux/regulator/consumer.h>
#include <trace/events/power.h>
#include <mach/clk-provider.h>
#include "clock.h"
@@ -53,20 +54,39 @@
/* Update voltage level given the current votes. */
static int update_vdd(struct clk_vdd_class *vdd_class)
{
- int level, rc;
+ int level, rc = 0, i;
+ struct regulator **r = vdd_class->regulator;
+ const int **vdd_uv = vdd_class->vdd_uv;
+ int max_level = vdd_class->num_levels - 1;
- for (level = vdd_class->num_levels-1; level > 0; level--)
+ for (level = max_level; level > 0; level--)
if (vdd_class->level_votes[level])
break;
if (level == vdd_class->cur_level)
return 0;
- rc = vdd_class->set_vdd(vdd_class, level);
+ for (i = 0; i < vdd_class->num_regulators; i++) {
+ rc = regulator_set_voltage(r[i], vdd_uv[level][i],
+ vdd_uv[max_level][i]);
+ if (rc)
+ goto set_voltage_fail;
+ }
+ if (vdd_class->set_vdd && !vdd_class->num_regulators)
+ rc = vdd_class->set_vdd(vdd_class, level);
+
if (!rc)
vdd_class->cur_level = level;
return rc;
+
+set_voltage_fail:
+ level = vdd_class->cur_level;
+ for (i--; i >= 0; i--)
+ regulator_set_voltage(r[i], vdd_uv[level][i],
+ vdd_uv[max_level][i]);
+
+ return rc;
}
/* Vote for a voltage level. */
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 475b483..528e9d5 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -21,6 +21,7 @@
#include <linux/clkdev.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
/*
@@ -42,14 +43,23 @@
/**
* struct clk_vdd_class - Voltage scaling class
* @class_name: name of the class
- * @set_vdd: function to call when applying a new voltage setting
- * @level_votes: array of votes for each level
+ * @regulator: array of regulators.
+ * @num_regulators: size of regulator array. Standard regulator APIs will be
+ used if this field > 0.
+ * @set_vdd: function to call when applying a new voltage setting.
+ * @vdd_uv: sorted 2D array of legal voltage settings. Indexed by level, then
+ regulator.
+ * @level_votes: array of votes for each level.
+ * @num_levels: specifies the size of level_votes array.
* @cur_level: the currently set voltage level
* @lock: lock to protect this struct
*/
struct clk_vdd_class {
const char *class_name;
+ struct regulator **regulator;
+ int num_regulators;
int (*set_vdd)(struct clk_vdd_class *v_class, int level);
+ const int **vdd_uv;
int *level_votes;
int num_levels;
unsigned long cur_level;
@@ -66,6 +76,20 @@
.lock = __MUTEX_INITIALIZER(_name.lock) \
}
+#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv) \
+ struct clk_vdd_class _name = { \
+ .class_name = #_name, \
+ .vdd_uv = _vdd_uv, \
+ .regulator = (struct regulator * [_num_regulators]) {}, \
+ .num_regulators = _num_regulators, \
+ .level_votes = (int [_num_levels]) {}, \
+ .num_levels = _num_levels, \
+ .cur_level = _num_levels, \
+ .lock = __MUTEX_INITIALIZER(_name.lock) \
+ }
+
+#define VDD_UV(...) ((int []){__VA_ARGS__})
+
enum handoff {
HANDOFF_ENABLED_CLK,
HANDOFF_DISABLED_CLK,