diff options
author | Paul Walmsley <paul@pwsan.com> | 2010-07-26 16:34:30 -0600 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2010-07-26 16:34:30 -0600 |
commit | 97d60162f64ef068b639d8a77ef3bc148baa53ad (patch) | |
tree | 33bdb47ec9f97e6404c864d59dbb362cae700a23 /arch/arm/mach-omap2/omap_hwmod.c | |
parent | 848240223c35fcc71c424ad51a8e8aef42d3879c (diff) | |
download | talos-op-linux-97d60162f64ef068b639d8a77ef3bc148baa53ad.tar.gz talos-op-linux-97d60162f64ef068b639d8a77ef3bc148baa53ad.zip |
OMAP: hwmod: allow omap_hwmod_late_init() caller to skip module idle in _setup()
On kernels that don't use the omap_device_enable() calls to enable
devices, leave all on-chip devices enabled in hwmod _setup().
Otherwise, accesses to those devices are likely to fail, crashing the
system. It's expected that kernels built without CONFIG_PM_RUNTIME
will be the primary use-case for this. This functionality is
controlled by adding an extra parameter to omap_hwmod_late_init().
This patch is based on the patch "OMAP: hwmod: don't auto-disable
hwmod when !CONFIG_PM_RUNTIME" by Kevin Hilman
<khilman@deeprootsystems.com>.
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index a23a60ad4059..b2c8e8760c80 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -764,6 +764,7 @@ static struct omap_hwmod *_lookup(const char *name) /** * _init_clocks - clk_get() all clocks associated with this hwmod * @oh: struct omap_hwmod * + * @data: not used; pass NULL * * Called by omap_hwmod_late_init() (after omap2_clk_init()). * Resolves all clock names embedded in the hwmod. Must be called @@ -771,7 +772,7 @@ static struct omap_hwmod *_lookup(const char *name) * has not yet been registered or if the clocks have already been * initialized, 0 on success, or a non-zero error on failure. */ -static int _init_clocks(struct omap_hwmod *oh) +static int _init_clocks(struct omap_hwmod *oh, void *data) { int ret = 0; @@ -996,19 +997,25 @@ 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. Must be called with omap_hwmod_mutex - * held. Returns -EINVAL if the hwmod is in the wrong state or returns - * 0. + * OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex held. + * @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. */ -static int _setup(struct omap_hwmod *oh) +static int _setup(struct omap_hwmod *oh, void *data) { int i, r; + u8 skip_setup_idle; - if (!oh) + if (!oh || !data) return -EINVAL; + skip_setup_idle = *(u8 *)data; + /* Set iclk autoidle mode */ if (oh->slaves_cnt > 0) { for (i = 0; i < oh->slaves_cnt; i++) { @@ -1050,7 +1057,7 @@ static int _setup(struct omap_hwmod *oh) } } - if (!(oh->flags & HWMOD_INIT_NO_IDLE)) + if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle) _omap_hwmod_idle(oh); return 0; @@ -1164,6 +1171,7 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name) /** * omap_hwmod_for_each - call function for each registered omap_hwmod * @fn: pointer to a callback function + * @data: void * data to pass to callback function * * Call @fn for each registered omap_hwmod, passing @data to each * function. @fn must return 0 for success or any other value for @@ -1172,7 +1180,8 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name) * caller of omap_hwmod_for_each(). @fn is called with * omap_hwmod_for_each() held. */ -int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh)) +int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), + void *data) { struct omap_hwmod *temp_oh; int ret; @@ -1182,7 +1191,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh)) mutex_lock(&omap_hwmod_mutex); list_for_each_entry(temp_oh, &omap_hwmod_list, node) { - ret = (*fn)(temp_oh); + ret = (*fn)(temp_oh, data); if (ret) break; } @@ -1229,24 +1238,28 @@ 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(void) +int omap_hwmod_late_init(u8 skip_setup_idle) { int r; /* XXX check return value */ - r = omap_hwmod_for_each(_init_clocks); + r = omap_hwmod_for_each(_init_clocks, NULL); WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n"); mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME); WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n", MPU_INITIATOR_NAME); - omap_hwmod_for_each(_setup); + if (skip_setup_idle) + pr_debug("omap_hwmod: will leave hwmods enabled during setup\n"); + + omap_hwmod_for_each(_setup, &skip_setup_idle); return 0; } |