OMAP2+: hwmod: add postsetup state
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>
This commit is contained in:
parent
e4dc8f507c
commit
2092e5ccf8
@ -312,6 +312,11 @@ static int __init _omap2_init_reprogram_sdrc(void)
|
|||||||
return v;
|
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
|
* Initialize asm_irq_base for entry-macro.S
|
||||||
*/
|
*/
|
||||||
@ -333,6 +338,8 @@ static inline void omap_irq_base_init(void)
|
|||||||
|
|
||||||
void __init omap2_init_common_infrastructure(void)
|
void __init omap2_init_common_infrastructure(void)
|
||||||
{
|
{
|
||||||
|
u8 postsetup_state;
|
||||||
|
|
||||||
pwrdm_init(powerdomains_omap);
|
pwrdm_init(powerdomains_omap);
|
||||||
clkdm_init(clockdomains_omap, clkdm_autodeps);
|
clkdm_init(clockdomains_omap, clkdm_autodeps);
|
||||||
if (cpu_is_omap242x())
|
if (cpu_is_omap242x())
|
||||||
@ -343,6 +350,16 @@ void __init omap2_init_common_infrastructure(void)
|
|||||||
omap3xxx_hwmod_init();
|
omap3xxx_hwmod_init();
|
||||||
else if (cpu_is_omap44xx())
|
else if (cpu_is_omap44xx())
|
||||||
omap44xx_hwmod_init();
|
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();
|
omap_pm_if_early_init();
|
||||||
|
|
||||||
@ -355,25 +372,16 @@ void __init omap2_init_common_infrastructure(void)
|
|||||||
else if (cpu_is_omap44xx())
|
else if (cpu_is_omap44xx())
|
||||||
omap4xxx_clk_init();
|
omap4xxx_clk_init();
|
||||||
else
|
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,
|
void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
|
||||||
struct omap_sdrc_params *sdrc_cs1)
|
struct omap_sdrc_params *sdrc_cs1)
|
||||||
{
|
{
|
||||||
u8 skip_setup_idle = 0;
|
|
||||||
|
|
||||||
omap_serial_early_init();
|
omap_serial_early_init();
|
||||||
|
|
||||||
#ifndef CONFIG_PM_RUNTIME
|
omap_hwmod_late_init();
|
||||||
skip_setup_idle = 1;
|
|
||||||
#endif
|
|
||||||
omap_hwmod_late_init(skip_setup_idle);
|
|
||||||
if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
|
if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
|
||||||
omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
|
omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
|
||||||
_omap2_init_reprogram_sdrc();
|
_omap2_init_reprogram_sdrc();
|
||||||
|
@ -1313,23 +1313,15 @@ static int _shutdown(struct omap_hwmod *oh)
|
|||||||
/**
|
/**
|
||||||
* _setup - do initial configuration of omap_hwmod
|
* _setup - do initial configuration of omap_hwmod
|
||||||
* @oh: struct 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
|
* Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
|
||||||
* OCP_SYSCONFIG register. @skip_setup_idle is intended to be used on
|
* OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the
|
||||||
* a system that will not call omap_hwmod_enable() to enable devices
|
* wrong state or returns 0.
|
||||||
* (e.g., a system without PM runtime). Returns -EINVAL if the hwmod
|
|
||||||
* is in the wrong state or returns 0.
|
|
||||||
*/
|
*/
|
||||||
static int _setup(struct omap_hwmod *oh, void *data)
|
static int _setup(struct omap_hwmod *oh, void *data)
|
||||||
{
|
{
|
||||||
int i, r;
|
int i, r;
|
||||||
u8 skip_setup_idle;
|
u8 postsetup_state;
|
||||||
|
|
||||||
if (!oh || !data)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
skip_setup_idle = *(u8 *)data;
|
|
||||||
|
|
||||||
/* Set iclk autoidle mode */
|
/* Set iclk autoidle mode */
|
||||||
if (oh->slaves_cnt > 0) {
|
if (oh->slaves_cnt > 0) {
|
||||||
@ -1349,7 +1341,6 @@ static int _setup(struct omap_hwmod *oh, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_init(&oh->_mutex);
|
|
||||||
oh->_state = _HWMOD_STATE_INITIALIZED;
|
oh->_state = _HWMOD_STATE_INITIALIZED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -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);
|
_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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1485,6 +1493,8 @@ int omap_hwmod_register(struct omap_hwmod *oh)
|
|||||||
|
|
||||||
list_add_tail(&oh->node, &omap_hwmod_list);
|
list_add_tail(&oh->node, &omap_hwmod_list);
|
||||||
|
|
||||||
|
mutex_init(&oh->_mutex);
|
||||||
|
|
||||||
oh->_state = _HWMOD_STATE_REGISTERED;
|
oh->_state = _HWMOD_STATE_REGISTERED;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -1585,13 +1595,12 @@ int omap_hwmod_init(struct omap_hwmod **ohs)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* omap_hwmod_late_init - do some post-clock framework initialization
|
* 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
|
* Must be called after omap2_clk_init(). Resolves the struct clk names
|
||||||
* to struct clk pointers for each registered omap_hwmod. Also calls
|
* to struct clk pointers for each registered omap_hwmod. Also calls
|
||||||
* _setup() on each hwmod. Returns 0.
|
* _setup() on each hwmod. Returns 0.
|
||||||
*/
|
*/
|
||||||
int omap_hwmod_late_init(u8 skip_setup_idle)
|
int omap_hwmod_late_init(void)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -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",
|
WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
|
||||||
MPU_INITIATOR_NAME);
|
MPU_INITIATOR_NAME);
|
||||||
|
|
||||||
if (skip_setup_idle)
|
omap_hwmod_for_each(_setup, NULL);
|
||||||
pr_debug("omap_hwmod: will leave hwmods enabled during setup\n");
|
|
||||||
|
|
||||||
omap_hwmod_for_each(_setup, &skip_setup_idle);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2132,3 +2138,41 @@ int omap_hwmod_for_each_by_class(const char *classname,
|
|||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
@ -462,6 +462,7 @@ struct omap_hwmod_class {
|
|||||||
* @response_lat: device OCP response latency (in interface clock cycles)
|
* @response_lat: device OCP response latency (in interface clock cycles)
|
||||||
* @_int_flags: internal-use hwmod flags
|
* @_int_flags: internal-use hwmod flags
|
||||||
* @_state: internal-use hwmod state
|
* @_state: internal-use hwmod state
|
||||||
|
* @_postsetup_state: internal-use state to leave the hwmod in after _setup()
|
||||||
* @flags: hwmod flags (documented below)
|
* @flags: hwmod flags (documented below)
|
||||||
* @omap_chip: OMAP chips this hwmod is present on
|
* @omap_chip: OMAP chips this hwmod is present on
|
||||||
* @_mutex: mutex serializing operations on this hwmod
|
* @_mutex: mutex serializing operations on this hwmod
|
||||||
@ -510,6 +511,7 @@ struct omap_hwmod {
|
|||||||
u8 hwmods_cnt;
|
u8 hwmods_cnt;
|
||||||
u8 _int_flags;
|
u8 _int_flags;
|
||||||
u8 _state;
|
u8 _state;
|
||||||
|
u8 _postsetup_state;
|
||||||
const struct omap_chip_id omap_chip;
|
const struct omap_chip_id omap_chip;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -519,7 +521,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh);
|
|||||||
struct omap_hwmod *omap_hwmod_lookup(const char *name);
|
struct omap_hwmod *omap_hwmod_lookup(const char *name);
|
||||||
int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
|
int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
|
||||||
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);
|
||||||
int _omap_hwmod_enable(struct omap_hwmod *oh);
|
int _omap_hwmod_enable(struct omap_hwmod *oh);
|
||||||
@ -566,6 +568,8 @@ int omap_hwmod_for_each_by_class(const char *classname,
|
|||||||
void *user),
|
void *user),
|
||||||
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
|
* Chip variant-specific hwmod init routines - XXX should be converted
|
||||||
* to use initcalls once the initial boot ordering is straightened out
|
* to use initcalls once the initial boot ordering is straightened out
|
||||||
|
Loading…
Reference in New Issue
Block a user