Skip to content

Commit 732dd0e

Browse files
Alex FridRohan Somvanshi
Alex Frid
authored and
Rohan Somvanshi
committed
ARM: tegra: dvfs: Add alternative dvfs frequency limits
Added an option to specify alternative dvfs frequency limits for each tegra clock domain. These alternative limits can be applied in some particularly extreme (e.g., slow) corner of process-temperature space with no effect on regular limits for the rest of the space. Bug 913884 Change-Id: I05e319b60f6dc6f4e7f15c7e677e5a3bce77f201 Signed-off-by: Alex Frid <[email protected]> Reviewed-on: http://git-master/r/70188 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Diwakar Tundlam <[email protected]> Tested-by: Diwakar Tundlam <[email protected]> Reviewed-by: Krishna Reddy <[email protected]> Reviewed-on: http://git-master/r/75614 Reviewed-by: Varun Wadekar <[email protected]> Tested-by: Varun Wadekar <[email protected]>
1 parent 8501e75 commit 732dd0e

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

arch/arm/mach-tegra/dvfs.c

+43-3
Original file line numberDiff line numberDiff line change
@@ -320,16 +320,23 @@ static int dvfs_rail_connect_to_regulator(struct dvfs_rail *rail)
320320
return 0;
321321
}
322322

323+
static inline unsigned long *dvfs_get_freqs(struct dvfs *d)
324+
{
325+
return (d->alt_freqs_state == ALT_FREQS_ENABLED) ?
326+
&d->alt_freqs[0] : &d->freqs[0];
327+
}
328+
323329
static int
324330
__tegra_dvfs_set_rate(struct dvfs *d, unsigned long rate)
325331
{
326332
int i = 0;
327333
int ret;
334+
unsigned long *freqs = dvfs_get_freqs(d);
328335

329-
if (d->freqs == NULL || d->millivolts == NULL)
336+
if (freqs == NULL || d->millivolts == NULL)
330337
return -ENODEV;
331338

332-
if (rate > d->freqs[d->num_freqs - 1]) {
339+
if (rate > freqs[d->num_freqs - 1]) {
333340
pr_warn("tegra_dvfs: rate %lu too high for dvfs on %s\n", rate,
334341
d->clk_name);
335342
return -EINVAL;
@@ -338,7 +345,7 @@ __tegra_dvfs_set_rate(struct dvfs *d, unsigned long rate)
338345
if (rate == 0) {
339346
d->cur_millivolts = 0;
340347
} else {
341-
while (i < d->num_freqs && rate > d->freqs[i])
348+
while (i < d->num_freqs && rate > freqs[i])
342349
i++;
343350

344351
if ((d->max_millivolts) &&
@@ -360,6 +367,31 @@ __tegra_dvfs_set_rate(struct dvfs *d, unsigned long rate)
360367
return ret;
361368
}
362369

370+
static inline int dvfs_alt_freqs_set(struct dvfs *d, bool enable)
371+
{
372+
if (d->alt_freqs_state == ALT_FREQS_NOT_SUPPORTED)
373+
return -ENOSYS;
374+
375+
d->alt_freqs_state = enable ? ALT_FREQS_ENABLED : ALT_FREQS_DISABLED;
376+
return 0;
377+
}
378+
379+
int tegra_dvfs_alt_freqs_set(struct dvfs *d, bool enable)
380+
{
381+
int ret;
382+
enum dvfs_alt_freqs old_state;
383+
384+
mutex_lock(&dvfs_lock);
385+
386+
old_state = d->alt_freqs_state;
387+
ret = dvfs_alt_freqs_set(d, enable);
388+
if (!ret && (old_state != d->alt_freqs_state))
389+
ret = __tegra_dvfs_set_rate(d, d->cur_rate);
390+
391+
mutex_unlock(&dvfs_lock);
392+
return ret;
393+
}
394+
363395
int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate)
364396
{
365397
int i;
@@ -370,6 +402,14 @@ int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate)
370402
if (!c->dvfs->millivolts)
371403
return -ENODEV;
372404

405+
/*
406+
* Predicted voltage can not be used across the switch to alternative
407+
* frequency limits. For now, just fail the call for clock that has
408+
* alternative limits initialized.
409+
*/
410+
if (c->dvfs->alt_freqs_state != ALT_FREQS_NOT_SUPPORTED)
411+
return -ENOSYS;
412+
373413
for (i = 0; i < c->dvfs->num_freqs; i++) {
374414
if (rate <= c->dvfs->freqs[i])
375415
break;

arch/arm/mach-tegra/dvfs.h

+11
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ struct dvfs_rail {
7373
struct rail_stats stats;
7474
};
7575

76+
enum dvfs_alt_freqs {
77+
ALT_FREQS_NOT_SUPPORTED = 0,
78+
ALT_FREQS_DISABLED,
79+
ALT_FREQS_ENABLED,
80+
};
81+
7682
struct dvfs {
7783
/* Used only by tegra2_clock.c */
7884
const char *clk_name;
@@ -82,9 +88,11 @@ struct dvfs {
8288
/* Must be initialized before tegra_dvfs_init */
8389
int freqs_mult;
8490
unsigned long freqs[MAX_DVFS_FREQS];
91+
unsigned long alt_freqs[MAX_DVFS_FREQS];
8592
const int *millivolts;
8693
struct dvfs_rail *dvfs_rail;
8794
bool auto_dvfs;
95+
enum dvfs_alt_freqs alt_freqs_state;
8896

8997
/* Filled in by tegra_dvfs_init */
9098
int max_millivolts;
@@ -116,6 +124,7 @@ struct dvfs_rail *tegra_dvfs_get_rail_by_name(const char *reg_id);
116124
int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate);
117125
void tegra_dvfs_core_cap_enable(bool enable);
118126
void tegra_dvfs_core_cap_level_set(int level);
127+
int tegra_dvfs_alt_freqs_set(struct dvfs *d, bool enable);
119128
#else
120129
static inline void tegra_soc_init_dvfs(void)
121130
{}
@@ -150,6 +159,8 @@ static inline void tegra_dvfs_core_cap_enable(bool enable)
150159
{}
151160
static inline void tegra_dvfs_core_cap_level_set(int level)
152161
{}
162+
static inline int tegra_dvfs_alt_freqs_set(struct dvfs *d, bool enable)
163+
{ return 0; }
153164
#endif
154165

155166
#ifndef CONFIG_ARCH_TEGRA_2x_SOC

0 commit comments

Comments
 (0)