Common Clk Framework
DVFS Roadmap
Mike Turquette
Linaro, Inc.
Not a how-to
Not a how-to
Not a tutorial
Not a how-to
Not a tutorial
Q&A at the end
"But I want to know how
to use the framework!"
● Gregory Clement (Free Electrons) did a
great overview presentation at ELC 2013
○ covers the CCF from the perspective of the
framework consumer
○ details construction of some DT bindings
○ http://events.linuxfoundation.
org/images/stories/slides/elc2013_clement.pdf
You are in luck
A quick recap
Where we are today
● Lots of ARM platforms converted to CCF
○ MIPS support merged and x86 patches on the list
● Many DT bindings
○ Some basic clock types have DT bindings
○ Many platform-specific clock types have bindings
● No new users of clk-private.h
○ Tegra migrated over to dynamic registration
○ OMAP is the only remaining user
■ Discussion on the list is promising
● http://article.gmane.org/gmane.linux.ports.arm.omap/94429
Open issues
● clk_round_rate 2GHz issue
● clk.c is too big
● clk-private.h
● __clk_get_name(...)
● clk_unregister and clk_put unimplemented
Various core design issues
● registration functions are ugly
● string name lookups for parent clocks
● initializing clocks in early init before slab is
up
The future
Last week's RFC
● Allows the clk api to re-enter itself
○ Rajagopal Venkat (ST-E/Linaro) had the idea to use
get_current() for establishing context
● Opens the door for dynamic voltage &
frequency scaling (dvfs)
○ accomplished via rate-change notifiers
● Series includes dvfs helper functions
○ convenient for existing users of the OPP library
○ platforms not using OPP library can register their
own callbacks
Why reentrancy?
Boring code
static bool clk_is_reentrant(void)
{
if (mutex_is_locked(&prepare_lock))
if ((void *) atomic_read(&context) == get_current())
return true;
return false;
}
static void clk_fwk_lock(void)
{
/* hold the framework-wide lock, context == NULL */
mutex_lock(&prepare_lock);
/* set context for any reentrant calls */
atomic_set(&context, (int) get_current());
}
static void clk_fwk_unlock(void)
{
/* clear the context */
atomic_set(&context, 0);
/* release the framework-wide lock, context == NULL */
mutex_unlock(&prepare_lock);
}
int clk_prepare(struct clk *clk)
{
int ret;
/* re-enter if call is from the same context */
if (clk_is_reentrant()) {
ret = __clk_prepare(clk);
goto out;
}
clk_fwk_lock();
ret = __clk_prepare(clk);
clk_fwk_unlock();
out:
return ret;
}
EXPORT_SYMBOL_GPL(clk_prepare);
Re-entering the clk api, slow parts
● clk_ops callbacks may now call top-level clk.
h apis
● clk_{un}prepare, clk_set_rate &
clk_set_parent may all call each other
○ above calls can also call clk_{en|dis}able
Re-entering the clk api, fast parts
● clk_{en|dis}able may call clk_{en|dis}able
● may not call other clk api functions
○ clk_{un}prepare, clk_set_rate & clk_set_parent may
sleep
Useful combinations
● clk_set_rate may now call clk_set_parent
○ does away with __clk_reparent(...)
● clk_set_parent may now call clk_{un}prepare
and clk_{en|dis}able
● clk_{un}prepare may call clk_{un}prepare
and clk_{en|dis}able
○ as shown in the amazing reentrancy diagram
● remove __clk_foo() functions in clk-provider.
h
● update users of __clk_foo() functions to use
the first class versions reentrantly
Todo
DVFS
DVFS
A proposal
Voltage scaling in notifiers
● clk_set_rate and clk_set_parent fire pre
rate-change notifiers and post rate-change
notifiers
○ call regulator_set_voltage()
● devices can register their own notifier
handlers
● clk_{en|dis}able and clk_{un}prepare do not
have notifiers
○ use run-time pm
More boring code
drivers/clk/dvfs.c
...
/* scaling up? scale voltage before frequency */
if (new_rate > old_rate) {
ret = regulator_set_voltage_tol(di->reg, volt_new, di->tol);
if (ret)
return notifier_from_errno(ret);
}
/* scaling down? scale voltage after frequency */
if (new_rate < old_rate) {
ret = regulator_set_voltage_tol(di->reg, volt_new, di->tol);
if (ret)
return notifier_from_errno(ret);
}
return NOTIFY_OK;
Key concepts
● dvfs is device-centric
○ regulator voltage is a function of a device operating
at a given rate
○ distinct from a clock operating at a given rate
● multiple devices may register voltage scaling
callbacks for the same clock
○ integrators do not have to consider all cases ahead
of time
○ driver authors use the voltages from their data sheet
Devfreq & cpufreq
● Frameworks implementing dvfs policy
○ policy should be built upon a common method of
implementing dvfs
● devfreq and cpufreq drivers can stop
managing regulators directly
○ removes another barrier from consolidating custom
ARM SoC cpufreq driver into something generic
■ cpufreq-cpu0.c?
Where does the data go?
● DT bindings for operating points
○ tie devices, clocks, frequencies, regulators and
voltages together in one place
● Need to gather requirements from you on
the needs of your platform
○ Ideally a single binding can work for all
● group clock rate changes as part of dvfs
transition
○ e.g. scaling CPU frequency requires async bridge
divider updates as well as changing DDR clock
speed
● centralized approach versus distributed
approach
○ must be easy for driver authors
DVFS unresolved topics
Alternative approach
● Create a new api
○ dvfs_set_rate() or dvfs_set_opp()
● Does away with relying on clock rate-change
notifiers
● Extra burden on driver authors to learn about
a new api/framework
○ Driver authors must choose whether to use
clk_set_rate or dvfs_set_rate
Questions?

LCA13: Common Clk Framework DVFS Roadmap

  • 1.
    Common Clk Framework DVFSRoadmap Mike Turquette Linaro, Inc.
  • 2.
  • 3.
    Not a how-to Nota tutorial
  • 4.
    Not a how-to Nota tutorial Q&A at the end
  • 5.
    "But I wantto know how to use the framework!"
  • 6.
    ● Gregory Clement(Free Electrons) did a great overview presentation at ELC 2013 ○ covers the CCF from the perspective of the framework consumer ○ details construction of some DT bindings ○ http://events.linuxfoundation. org/images/stories/slides/elc2013_clement.pdf You are in luck
  • 7.
  • 8.
    Where we aretoday ● Lots of ARM platforms converted to CCF ○ MIPS support merged and x86 patches on the list ● Many DT bindings ○ Some basic clock types have DT bindings ○ Many platform-specific clock types have bindings ● No new users of clk-private.h ○ Tegra migrated over to dynamic registration ○ OMAP is the only remaining user ■ Discussion on the list is promising ● http://article.gmane.org/gmane.linux.ports.arm.omap/94429
  • 9.
    Open issues ● clk_round_rate2GHz issue ● clk.c is too big ● clk-private.h ● __clk_get_name(...) ● clk_unregister and clk_put unimplemented
  • 10.
    Various core designissues ● registration functions are ugly ● string name lookups for parent clocks ● initializing clocks in early init before slab is up
  • 11.
  • 12.
    Last week's RFC ●Allows the clk api to re-enter itself ○ Rajagopal Venkat (ST-E/Linaro) had the idea to use get_current() for establishing context ● Opens the door for dynamic voltage & frequency scaling (dvfs) ○ accomplished via rate-change notifiers ● Series includes dvfs helper functions ○ convenient for existing users of the OPP library ○ platforms not using OPP library can register their own callbacks
  • 13.
  • 15.
  • 16.
    static bool clk_is_reentrant(void) { if(mutex_is_locked(&prepare_lock)) if ((void *) atomic_read(&context) == get_current()) return true; return false; }
  • 17.
    static void clk_fwk_lock(void) { /*hold the framework-wide lock, context == NULL */ mutex_lock(&prepare_lock); /* set context for any reentrant calls */ atomic_set(&context, (int) get_current()); } static void clk_fwk_unlock(void) { /* clear the context */ atomic_set(&context, 0); /* release the framework-wide lock, context == NULL */ mutex_unlock(&prepare_lock); }
  • 18.
    int clk_prepare(struct clk*clk) { int ret; /* re-enter if call is from the same context */ if (clk_is_reentrant()) { ret = __clk_prepare(clk); goto out; } clk_fwk_lock(); ret = __clk_prepare(clk); clk_fwk_unlock(); out: return ret; } EXPORT_SYMBOL_GPL(clk_prepare);
  • 20.
    Re-entering the clkapi, slow parts ● clk_ops callbacks may now call top-level clk. h apis ● clk_{un}prepare, clk_set_rate & clk_set_parent may all call each other ○ above calls can also call clk_{en|dis}able
  • 21.
    Re-entering the clkapi, fast parts ● clk_{en|dis}able may call clk_{en|dis}able ● may not call other clk api functions ○ clk_{un}prepare, clk_set_rate & clk_set_parent may sleep
  • 22.
    Useful combinations ● clk_set_ratemay now call clk_set_parent ○ does away with __clk_reparent(...) ● clk_set_parent may now call clk_{un}prepare and clk_{en|dis}able ● clk_{un}prepare may call clk_{un}prepare and clk_{en|dis}able ○ as shown in the amazing reentrancy diagram
  • 23.
    ● remove __clk_foo()functions in clk-provider. h ● update users of __clk_foo() functions to use the first class versions reentrantly Todo
  • 24.
  • 25.
  • 26.
    Voltage scaling innotifiers ● clk_set_rate and clk_set_parent fire pre rate-change notifiers and post rate-change notifiers ○ call regulator_set_voltage() ● devices can register their own notifier handlers ● clk_{en|dis}able and clk_{un}prepare do not have notifiers ○ use run-time pm
  • 27.
  • 28.
    drivers/clk/dvfs.c ... /* scaling up?scale voltage before frequency */ if (new_rate > old_rate) { ret = regulator_set_voltage_tol(di->reg, volt_new, di->tol); if (ret) return notifier_from_errno(ret); } /* scaling down? scale voltage after frequency */ if (new_rate < old_rate) { ret = regulator_set_voltage_tol(di->reg, volt_new, di->tol); if (ret) return notifier_from_errno(ret); } return NOTIFY_OK;
  • 30.
    Key concepts ● dvfsis device-centric ○ regulator voltage is a function of a device operating at a given rate ○ distinct from a clock operating at a given rate ● multiple devices may register voltage scaling callbacks for the same clock ○ integrators do not have to consider all cases ahead of time ○ driver authors use the voltages from their data sheet
  • 31.
    Devfreq & cpufreq ●Frameworks implementing dvfs policy ○ policy should be built upon a common method of implementing dvfs ● devfreq and cpufreq drivers can stop managing regulators directly ○ removes another barrier from consolidating custom ARM SoC cpufreq driver into something generic ■ cpufreq-cpu0.c?
  • 32.
    Where does thedata go? ● DT bindings for operating points ○ tie devices, clocks, frequencies, regulators and voltages together in one place ● Need to gather requirements from you on the needs of your platform ○ Ideally a single binding can work for all
  • 33.
    ● group clockrate changes as part of dvfs transition ○ e.g. scaling CPU frequency requires async bridge divider updates as well as changing DDR clock speed ● centralized approach versus distributed approach ○ must be easy for driver authors DVFS unresolved topics
  • 34.
    Alternative approach ● Createa new api ○ dvfs_set_rate() or dvfs_set_opp() ● Does away with relying on clock rate-change notifiers ● Extra burden on driver authors to learn about a new api/framework ○ Driver authors must choose whether to use clk_set_rate or dvfs_set_rate
  • 35.