Skip to content

Commit

Permalink
OMAP2+: hwmod: add postsetup state
Browse files Browse the repository at this point in the history
Allow board files and OMAP core code to control the state that some or
all of the hwmods end up in at the end of _setup() (called by
omap_hwmod_late_init() ).  Reimplement the old skip_setup_idle code in
terms of this new postsetup state code.

There are two use-cases for this patch: the !CONFIG_PM_RUNTIME case,
in which all IP blocks should stay enabled after _setup() finishes;
and the MPU watchdog case, in which the watchdog IP block should enter
idle if watchdog coverage of kernel initialization is desired, and
should be disabled otherwise.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Benoît Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Charulatha Varadarajan <charu@ti.com>
  • Loading branch information
Paul Walmsley committed Dec 22, 2010
1 parent e4dc8f5 commit 2092e5c
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 32 deletions.
32 changes: 20 additions & 12 deletions arch/arm/mach-omap2/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,11 @@ static int __init _omap2_init_reprogram_sdrc(void)
return v;
}

static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
{
return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
}

/*
* Initialize asm_irq_base for entry-macro.S
*/
Expand All @@ -333,6 +338,8 @@ static inline void omap_irq_base_init(void)

void __init omap2_init_common_infrastructure(void)
{
u8 postsetup_state;

pwrdm_init(powerdomains_omap);
clkdm_init(clockdomains_omap, clkdm_autodeps);
if (cpu_is_omap242x())
Expand All @@ -343,6 +350,16 @@ void __init omap2_init_common_infrastructure(void)
omap3xxx_hwmod_init();
else if (cpu_is_omap44xx())
omap44xx_hwmod_init();
else
pr_err("Could not init hwmod data - unknown SoC\n");

/* Set the default postsetup state for all hwmods */
#ifdef CONFIG_PM_RUNTIME
postsetup_state = _HWMOD_STATE_IDLE;
#else
postsetup_state = _HWMOD_STATE_ENABLED;
#endif
omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);

omap_pm_if_early_init();

Expand All @@ -355,25 +372,16 @@ void __init omap2_init_common_infrastructure(void)
else if (cpu_is_omap44xx())
omap4xxx_clk_init();
else
pr_err("Could not init clock framework - unknown CPU\n");
pr_err("Could not init clock framework - unknown SoC\n");
}

/*
* XXX Ideally, this function will dwindle into nothingness over time;
* almost all device init code should be possible through initcalls
* and other generalized mechanisms
*/
void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
struct omap_sdrc_params *sdrc_cs1)
{
u8 skip_setup_idle = 0;

omap_serial_early_init();

#ifndef CONFIG_PM_RUNTIME
skip_setup_idle = 1;
#endif
omap_hwmod_late_init(skip_setup_idle);
omap_hwmod_late_init();

if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
_omap2_init_reprogram_sdrc();
Expand Down
82 changes: 63 additions & 19 deletions arch/arm/mach-omap2/omap_hwmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -1313,23 +1313,15 @@ static int _shutdown(struct omap_hwmod *oh)
/**
* _setup - do initial configuration of omap_hwmod
* @oh: struct omap_hwmod *
* @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
*
* Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
* OCP_SYSCONFIG register. @skip_setup_idle is intended to be used on
* a system that will not call omap_hwmod_enable() to enable devices
* (e.g., a system without PM runtime). Returns -EINVAL if the hwmod
* is in the wrong state or returns 0.
* OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the
* wrong state or returns 0.
*/
static int _setup(struct omap_hwmod *oh, void *data)
{
int i, r;
u8 skip_setup_idle;

if (!oh || !data)
return -EINVAL;

skip_setup_idle = *(u8 *)data;
u8 postsetup_state;

/* Set iclk autoidle mode */
if (oh->slaves_cnt > 0) {
Expand All @@ -1349,7 +1341,6 @@ static int _setup(struct omap_hwmod *oh, void *data)
}
}

mutex_init(&oh->_mutex);
oh->_state = _HWMOD_STATE_INITIALIZED;

/*
Expand Down Expand Up @@ -1383,8 +1374,25 @@ static int _setup(struct omap_hwmod *oh, void *data)
}
}

if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle)
postsetup_state = oh->_postsetup_state;
if (postsetup_state == _HWMOD_STATE_UNKNOWN)
postsetup_state = _HWMOD_STATE_ENABLED;

/*
* XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data -
* it should be set by the core code as a runtime flag during startup
*/
if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
(postsetup_state == _HWMOD_STATE_IDLE))
postsetup_state = _HWMOD_STATE_ENABLED;

if (postsetup_state == _HWMOD_STATE_IDLE)
_omap_hwmod_idle(oh);
else if (postsetup_state == _HWMOD_STATE_DISABLED)
_shutdown(oh);
else if (postsetup_state != _HWMOD_STATE_ENABLED)
WARN(1, "hwmod: %s: unknown postsetup state %d! defaulting to enabled\n",
oh->name, postsetup_state);

return 0;
}
Expand Down Expand Up @@ -1485,6 +1493,8 @@ int omap_hwmod_register(struct omap_hwmod *oh)

list_add_tail(&oh->node, &omap_hwmod_list);

mutex_init(&oh->_mutex);

oh->_state = _HWMOD_STATE_REGISTERED;

ret = 0;
Expand Down Expand Up @@ -1585,13 +1595,12 @@ int omap_hwmod_init(struct omap_hwmod **ohs)

/**
* omap_hwmod_late_init - do some post-clock framework initialization
* @skip_setup_idle: if 1, do not idle hwmods in _setup()
*
* Must be called after omap2_clk_init(). Resolves the struct clk names
* to struct clk pointers for each registered omap_hwmod. Also calls
* _setup() on each hwmod. Returns 0.
*/
int omap_hwmod_late_init(u8 skip_setup_idle)
int omap_hwmod_late_init(void)
{
int r;

Expand All @@ -1603,10 +1612,7 @@ int omap_hwmod_late_init(u8 skip_setup_idle)
WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
MPU_INITIATOR_NAME);

if (skip_setup_idle)
pr_debug("omap_hwmod: will leave hwmods enabled during setup\n");

omap_hwmod_for_each(_setup, &skip_setup_idle);
omap_hwmod_for_each(_setup, NULL);

return 0;
}
Expand Down Expand Up @@ -2132,3 +2138,41 @@ int omap_hwmod_for_each_by_class(const char *classname,
return ret;
}

/**
* omap_hwmod_set_postsetup_state - set the post-_setup() state for this hwmod
* @oh: struct omap_hwmod *
* @state: state that _setup() should leave the hwmod in
*
* Sets the hwmod state that @oh will enter at the end of _setup() (called by
* omap_hwmod_late_init()). Only valid to call between calls to
* omap_hwmod_init() and omap_hwmod_late_init(). Returns 0 upon success or
* -EINVAL if there is a problem with the arguments or if the hwmod is
* in the wrong state.
*/
int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
{
int ret;

if (!oh)
return -EINVAL;

if (state != _HWMOD_STATE_DISABLED &&
state != _HWMOD_STATE_ENABLED &&
state != _HWMOD_STATE_IDLE)
return -EINVAL;

mutex_lock(&oh->_mutex);

if (oh->_state != _HWMOD_STATE_REGISTERED) {
ret = -EINVAL;
goto ohsps_unlock;
}

oh->_postsetup_state = state;
ret = 0;

ohsps_unlock:
mutex_unlock(&oh->_mutex);

return ret;
}
6 changes: 5 additions & 1 deletion arch/arm/plat-omap/include/plat/omap_hwmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ struct omap_hwmod_class {
* @response_lat: device OCP response latency (in interface clock cycles)
* @_int_flags: internal-use hwmod flags
* @_state: internal-use hwmod state
* @_postsetup_state: internal-use state to leave the hwmod in after _setup()
* @flags: hwmod flags (documented below)
* @omap_chip: OMAP chips this hwmod is present on
* @_mutex: mutex serializing operations on this hwmod
Expand Down Expand Up @@ -510,6 +511,7 @@ struct omap_hwmod {
u8 hwmods_cnt;
u8 _int_flags;
u8 _state;
u8 _postsetup_state;
const struct omap_chip_id omap_chip;
};

Expand All @@ -519,7 +521,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh);
struct omap_hwmod *omap_hwmod_lookup(const char *name);
int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
void *data);
int omap_hwmod_late_init(u8 skip_setup_idle);
int omap_hwmod_late_init(void);

int omap_hwmod_enable(struct omap_hwmod *oh);
int _omap_hwmod_enable(struct omap_hwmod *oh);
Expand Down Expand Up @@ -566,6 +568,8 @@ int omap_hwmod_for_each_by_class(const char *classname,
void *user),
void *user);

int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);

/*
* Chip variant-specific hwmod init routines - XXX should be converted
* to use initcalls once the initial boot ordering is straightened out
Expand Down

0 comments on commit 2092e5c

Please sign in to comment.