summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/dvfs.h8
-rw-r--r--arch/arm/mach-tegra/tegra11_dvfs.c69
2 files changed, 44 insertions, 33 deletions
diff --git a/arch/arm/mach-tegra/dvfs.h b/arch/arm/mach-tegra/dvfs.h
index c8ed6b6abb6a..659d8163e6d4 100644
--- a/arch/arm/mach-tegra/dvfs.h
+++ b/arch/arm/mach-tegra/dvfs.h
@@ -102,9 +102,9 @@ struct dvfs {
struct cpu_cvb_dvfs_parameters {
unsigned long freq;
- u32 c0;
- u32 c1;
- u32 c2;
+ int c0;
+ int c1;
+ int c2;
};
struct cpu_cvb_dvfs {
@@ -113,6 +113,8 @@ struct cpu_cvb_dvfs {
int min_mv;
int margin;
int freqs_mult;
+ int speedo_scale;
+ int voltage_scale;
struct cpu_cvb_dvfs_parameters cvb_table[MAX_DVFS_FREQS];
};
diff --git a/arch/arm/mach-tegra/tegra11_dvfs.c b/arch/arm/mach-tegra/tegra11_dvfs.c
index 8778b02a787b..cbd74f98aa76 100644
--- a/arch/arm/mach-tegra/tegra11_dvfs.c
+++ b/arch/arm/mach-tegra/tegra11_dvfs.c
@@ -36,6 +36,7 @@ static bool tegra_dvfs_core_disabled;
/* FIXME: need tegra11 step */
#define VDD_SAFE_STEP 100
+#define CVB_ALIGN_STEP_UV 12500
static struct dvfs_rail tegra11_dvfs_rail_vdd_cpu = {
.reg_id = "vdd_cpu",
@@ -62,29 +63,31 @@ static struct dvfs_rail *tegra11_dvfs_rails[] = {
static struct cpu_cvb_dvfs cpu_cvb_dvfs_table[] = {
{
.speedo_id = 0,
- .max_mv = 1150,
+ .max_mv = 1250,
.min_mv = 850,
.margin = 103,
.freqs_mult = MHZ,
+ .speedo_scale = 100,
+ .voltage_scale = 100,
.cvb_table = {
- /*f c0, c1, c2 */
- { 306, 800, 0, 0},
- { 408, 812, 0, 0},
- { 510, 825, 0, 0},
- { 612, 850, 0, 0},
- { 714, 850, 0, 0},
- { 816, 858, 0, 0},
- { 918, 900, 0, 0},
- {1020, 912, 0, 0},
- {1122, 937, 0, 0},
- {1224, 937, 0, 0},
- {1326, 975, 0, 0},
- {1428, 1000, 0, 0},
- {1530, 1000, 0, 0},
- {1632, 1100, 0, 0},
- {1734, 1150, 0, 0},
- {1836, 1200, 0, 0},
- { 0, 0, 0, 0},
+ /*f c0, c1, c2 */
+ { 306, 9251, 12837, -570},
+ { 408, 11737, 12957, -570},
+ { 510, 14282, 13076, -570},
+ { 612, 16887, 13196, -570},
+ { 714, 19552, 13315, -570},
+ { 816, 22277, 13435, -570},
+ { 918, 25061, 13554, -570},
+ {1020, 27905, 13674, -570},
+ {1122, 30809, 13793, -570},
+ {1224, 33773, 13913, -570},
+ {1326, 36797, 14032, -570},
+ {1428, 39880, 14152, -570},
+ {1530, 43023, 14271, -570},
+ {1632, 46226, 14391, -570},
+ {1734, 49489, 14511, -570},
+ {1836, 52812, 14630, -570},
+ { 0, 0, 0, 0},
},
}
};
@@ -330,20 +333,25 @@ static bool __init match_dvfs_one(struct dvfs *d, int speedo_id, int process_id)
return true;
}
-static inline int round_cvb_voltage(int mv)
-{
- /* round to 12.5mV */
- return DIV_ROUND_UP(mv * 2, 25) * 25 / 2;
-}
-static inline int get_cvb_voltage(int speedo,
+/* cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) / v_scale */
+static inline int get_cvb_voltage(int speedo, int s_scale,
struct cpu_cvb_dvfs_parameters *cvb)
{
- /* FIXME: normalize */
- int mv = cvb->c0 + cvb->c1 * speedo + cvb->c2 * speedo * speedo;
+ /* apply only speedo scale: output mv = cvb_mv * v_scale */
+ int mv;
+ mv = DIV_ROUND_CLOSEST(cvb->c2 * speedo, s_scale);
+ mv = DIV_ROUND_CLOSEST((mv + cvb->c1) * speedo, s_scale) + cvb->c0;
return mv;
}
+static inline int round_cvb_voltage(int mv, int v_scale)
+{
+ /* combined: apply voltage scale and round to cvb alignment step */
+ return DIV_ROUND_UP(mv * 1000, v_scale * CVB_ALIGN_STEP_UV) *
+ CVB_ALIGN_STEP_UV / 1000;
+}
+
static int __init set_cpu_dvfs_data(int speedo_id, struct dvfs *cpu_dvfs,
struct tegra_cl_dvfs_dfll_data *dfll_data, int *max_freq_index)
{
@@ -378,8 +386,8 @@ static int __init set_cpu_dvfs_data(int speedo_id, struct dvfs *cpu_dvfs,
if (!cvb->freq)
break;
- mv = get_cvb_voltage(speedo, cvb);
- dfll_mv = round_cvb_voltage(mv);
+ mv = get_cvb_voltage(speedo, d->speedo_scale, cvb);
+ dfll_mv = round_cvb_voltage(mv, d->voltage_scale);
dfll_mv = max(dfll_mv, d->min_mv);
if (dfll_mv > d->max_mv)
break;
@@ -396,7 +404,8 @@ static int __init set_cpu_dvfs_data(int speedo_id, struct dvfs *cpu_dvfs,
if (!j || (dfll_mv > cpu_dfll_millivolts[j - 1])) {
cpu_dvfs->freqs[j] = cvb->freq;
cpu_dfll_millivolts[j] = dfll_mv;
- mv = round_cvb_voltage(mv * d->margin / 100);
+ mv = mv * d->margin / 100;
+ mv = round_cvb_voltage(mv, d->voltage_scale);
cpu_millivolts[j] = max(mv, d->min_mv);
j++;
} else {