OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework
Duplicate the existing API for clockdomain enable from clock to enable a clock domain from hwmod framework. This will be needed when the hwmod framework will move from the current clock centric approach to the module based approach. These APIs are returning 0 for the moment for OMAP2 and OMAP3 until their hwmods are updated with the clksm attribute. Signed-off-by: Benoit Cousson <b-cousson@ti.com> Cc: Kevin Hilman <khilman@ti.com> Cc: Paul Walmsley <paul@pwsan.com> Cc: Rajendra Nayak <rnayak@ti.com> Signed-off-by: Paul Walmsley <paul@pwsan.com>
This commit is contained in:
parent
a5122ff8ce
commit
113a74137f
2 changed files with 116 additions and 43 deletions
|
@ -796,7 +796,50 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
|
|||
}
|
||||
|
||||
|
||||
/* Clockdomain-to-clock framework interface code */
|
||||
/* Clockdomain-to-clock/hwmod framework interface code */
|
||||
|
||||
static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
|
||||
{
|
||||
if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* For arch's with no autodeps, clkcm_clk_enable
|
||||
* should be called for every clock instance or hwmod that is
|
||||
* enabled, so the clkdm can be force woken up.
|
||||
*/
|
||||
if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps)
|
||||
return 0;
|
||||
|
||||
arch_clkdm->clkdm_clk_enable(clkdm);
|
||||
pwrdm_wait_transition(clkdm->pwrdm.ptr);
|
||||
pwrdm_clkdm_state_switch(clkdm);
|
||||
|
||||
pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
|
||||
{
|
||||
if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
|
||||
return -EINVAL;
|
||||
|
||||
if (atomic_read(&clkdm->usecount) == 0) {
|
||||
WARN_ON(1); /* underflow */
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (atomic_dec_return(&clkdm->usecount) > 0)
|
||||
return 0;
|
||||
|
||||
arch_clkdm->clkdm_clk_disable(clkdm);
|
||||
pwrdm_clkdm_state_switch(clkdm);
|
||||
|
||||
pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* clkdm_clk_enable - add an enabled downstream clock to this clkdm
|
||||
|
@ -819,24 +862,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
|
|||
* downstream clocks for debugging purposes?
|
||||
*/
|
||||
|
||||
if (!clkdm || !clk)
|
||||
if (!clk)
|
||||
return -EINVAL;
|
||||
|
||||
if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
|
||||
return -EINVAL;
|
||||
|
||||
if (atomic_inc_return(&clkdm->usecount) > 1)
|
||||
return 0;
|
||||
|
||||
/* Clockdomain now has one enabled downstream clock */
|
||||
|
||||
pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
|
||||
clk->name);
|
||||
|
||||
arch_clkdm->clkdm_clk_enable(clkdm);
|
||||
pwrdm_clkdm_state_switch(clkdm);
|
||||
|
||||
return 0;
|
||||
return _clkdm_clk_hwmod_enable(clkdm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -849,9 +878,8 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
|
|||
* clockdomain usecount goes to 0, put the clockdomain to sleep
|
||||
* (software-supervised mode) or remove the clkdm autodependencies
|
||||
* (hardware-supervised mode). Returns -EINVAL if passed null
|
||||
* pointers; -ERANGE if the @clkdm usecount underflows and debugging
|
||||
* is enabled; or returns 0 upon success or if the clockdomain is in
|
||||
* hwsup idle mode.
|
||||
* pointers; -ERANGE if the @clkdm usecount underflows; or returns 0
|
||||
* upon success or if the clockdomain is in hwsup idle mode.
|
||||
*/
|
||||
int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
|
||||
{
|
||||
|
@ -860,30 +888,72 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
|
|||
* downstream clocks for debugging purposes?
|
||||
*/
|
||||
|
||||
if (!clkdm || !clk)
|
||||
if (!clk)
|
||||
return -EINVAL;
|
||||
|
||||
if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (atomic_read(&clkdm->usecount) == 0) {
|
||||
WARN_ON(1); /* underflow */
|
||||
return -ERANGE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (atomic_dec_return(&clkdm->usecount) > 0)
|
||||
return 0;
|
||||
|
||||
/* All downstream clocks of this clockdomain are now disabled */
|
||||
|
||||
pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
|
||||
clk->name);
|
||||
|
||||
arch_clkdm->clkdm_clk_disable(clkdm);
|
||||
pwrdm_clkdm_state_switch(clkdm);
|
||||
|
||||
return 0;
|
||||
return _clkdm_clk_hwmod_disable(clkdm);
|
||||
}
|
||||
|
||||
/**
|
||||
* clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
|
||||
* @clkdm: struct clockdomain *
|
||||
* @oh: struct omap_hwmod * of the enabled downstream hwmod
|
||||
*
|
||||
* Increment the usecount of the clockdomain @clkdm and ensure that it
|
||||
* is awake before @oh is enabled. Intended to be called by
|
||||
* module_enable() code.
|
||||
* If the clockdomain is in software-supervised idle mode, force the
|
||||
* clockdomain to wake. If the clockdomain is in hardware-supervised idle
|
||||
* mode, add clkdm-pwrdm autodependencies, to ensure that devices in the
|
||||
* clockdomain can be read from/written to by on-chip processors.
|
||||
* Returns -EINVAL if passed null pointers;
|
||||
* returns 0 upon success or if the clockdomain is in hwsup idle mode.
|
||||
*/
|
||||
int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
|
||||
{
|
||||
/* The clkdm attribute does not exist yet prior OMAP4 */
|
||||
if (cpu_is_omap24xx() || cpu_is_omap34xx())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* XXX Rewrite this code to maintain a list of enabled
|
||||
* downstream hwmods for debugging purposes?
|
||||
*/
|
||||
|
||||
if (!oh)
|
||||
return -EINVAL;
|
||||
|
||||
return _clkdm_clk_hwmod_enable(clkdm);
|
||||
}
|
||||
|
||||
/**
|
||||
* clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm
|
||||
* @clkdm: struct clockdomain *
|
||||
* @oh: struct omap_hwmod * of the disabled downstream hwmod
|
||||
*
|
||||
* Decrement the usecount of this clockdomain @clkdm when @oh is
|
||||
* disabled. Intended to be called by module_disable() code.
|
||||
* If the clockdomain usecount goes to 0, put the clockdomain to sleep
|
||||
* (software-supervised mode) or remove the clkdm autodependencies
|
||||
* (hardware-supervised mode).
|
||||
* Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount
|
||||
* underflows; or returns 0 upon success or if the clockdomain is in hwsup
|
||||
* idle mode.
|
||||
*/
|
||||
int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
|
||||
{
|
||||
/* The clkdm attribute does not exist yet prior OMAP4 */
|
||||
if (cpu_is_omap24xx() || cpu_is_omap34xx())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* XXX Rewrite this code to maintain a list of enabled
|
||||
* downstream hwmods for debugging purposes?
|
||||
*/
|
||||
|
||||
if (!oh)
|
||||
return -EINVAL;
|
||||
|
||||
return _clkdm_clk_hwmod_disable(clkdm);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "powerdomain.h"
|
||||
#include <plat/clock.h>
|
||||
#include <plat/omap_hwmod.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
/*
|
||||
|
@ -183,6 +184,8 @@ int clkdm_sleep(struct clockdomain *clkdm);
|
|||
|
||||
int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
|
||||
int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
|
||||
int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
|
||||
int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
|
||||
|
||||
extern void __init omap2xxx_clockdomains_init(void);
|
||||
extern void __init omap3xxx_clockdomains_init(void);
|
||||
|
|
Loading…
Reference in a new issue