Common clock and dvfs
Saravana Kannan
skannan at codeaurora.org
Fri Apr 22 21:21:26 EDT 2011
On 04/22/2011 12:37 PM, Thomas Gleixner wrote:
> On Fri, 22 Apr 2011, Colin Cross wrote:
>
>> Is the clock api the right place to do dvfs, or should the clock api
>> be kept simple, and more complicated operations like dvfs be kept
>> outside?
>
> I think it's an orthogonal issue which can be solved once we have
> generic implementations in place for clk_ functions which result in
> DFVS relevant changes.
>
> clk_prepare()
> {
> lock_tree();
> if (dvfs_validate())
> return -ECRAP;
> prepare();
> unlock_tree();
> }
>
> clk_unprepare()
> {
> lock_tree();
> unprepare();
> dvfs_recalc();
> unlock_tree();
> }
>
> clk_set_rate()
> {
> lock_tree();
>
> if (rate> clk->rate&& dvfs_prevalidate(rate))
> return -ECRAP;
>
> set_and_propagate_rate();
>
> if (rate< old->rate)
> dvfs_recalc();
>
> unlock_tree();
> }
I understand that this is just some example code, but I'm not sure how
accurate you were trying to be. So, I will assume the worst.
I really don't like this lock the whole clock tree approach for DVFS. I
think a better approach would be something like this:
struct dvfs_tuple {
long max_rate; /* Max rate for this DVFS level. */
int dvfs_level;
};
/* Yeah, bad name. pick what you like. */
struct dvfs_class {
int *level_cnt;
int num_levels;
int (*dvfs_update) (int level);
mutex lock;
}
stuct clk {
...
/* Last entry would have {LONG_MAX, highest level in dvfs}, */
struct dvfs_tuple *dvfs_list;
struct dvfs_class *dvfs_class;
}
Then
clk_prepare() {
for each dvfs tuple {
if current_rate <= max_rate; {
level = dvfs_level;
break;
}
}
lock(dvfs_class->mutex);
clk->dvfs_class->level_cnt[level]++;
/* Find highest level in this dvfs class with non-zero count */
if(clk->dvfs_class->update(highest_level))
return -ECRAP;
/* Yes, I see locking err, but you get the point */
unlock(dvfs_class->mutex);
clk->ops->prepare(clk);
}
I did some crappy factorization of functions, returning -ECRAP without
unlocking, etc, but you get the point.
Whether the "level" translates to controlling power supply A or B or A &
B is upto the implementation of dvfs_class->dvfs_update() which is per
SOC/mach/arch.
This will keep the dvfs data structure common for all clocks, remove the
need to traverse the entire tree and keep the generic code agnostic of
1-1 vs. many-1 vs many-many.
> We can put the dvfs functions into the propagation code as well and
> back out there when dvfs tells us. That probably works nicely for
> prepare and unprepare, but might be complex for set_rate in the actual
> set_rate propagation (except when the rate is less than the original
> one).
For set rate, you lock the dvfs class, increment the count for the new
rate's dvfs_level, decrement it for the previous dvfs level, and then
call dvfs_update() with the max level in that class, unlock dvfs_class.
Thanks,
Saravana
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
More information about the linux-arm-kernel
mailing list