Skip to content

Commit

Permalink
OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod fra…
Browse files Browse the repository at this point in the history
…mework

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>
  • Loading branch information
Benoit Cousson authored and Paul Walmsley committed Jul 10, 2011
1 parent a5122ff commit 113a741
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 36 deletions.
142 changes: 106 additions & 36 deletions arch/arm/mach-omap2/clockdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}

/**
Expand All @@ -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)
{
Expand All @@ -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 _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;

#ifdef DEBUG
if (atomic_read(&clkdm->usecount) == 0) {
WARN_ON(1); /* underflow */
return -ERANGE;
}
#endif
return _clkdm_clk_hwmod_enable(clkdm);
}

if (atomic_dec_return(&clkdm->usecount) > 0)
/**
* 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;

/* All downstream clocks of this clockdomain are now disabled */

pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
clk->name);
/*
* XXX Rewrite this code to maintain a list of enabled
* downstream hwmods for debugging purposes?
*/

arch_clkdm->clkdm_clk_disable(clkdm);
pwrdm_clkdm_state_switch(clkdm);
if (!oh)
return -EINVAL;

return 0;
return _clkdm_clk_hwmod_disable(clkdm);
}

3 changes: 3 additions & 0 deletions arch/arm/mach-omap2/clockdomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "powerdomain.h"
#include <plat/clock.h>
#include <plat/omap_hwmod.h>
#include <plat/cpu.h>

/*
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 113a741

Please sign in to comment.