@@ -268,9 +268,6 @@ void omap2_clk_disable(struct clk *clk)
clk->ops->disable(clk);
}
- if (clk->clkdm)
- clkdm_clk_disable(clk->clkdm, clk);
-
if (clk->parent)
omap2_clk_disable(clk->parent);
}
@@ -308,30 +305,18 @@ int omap2_clk_enable(struct clk *clk)
}
}
- if (clk->clkdm) {
- ret = clkdm_clk_enable(clk->clkdm, clk);
- if (ret) {
- WARN(1, "clock: %s: could not enable clockdomain %s: "
- "%d\n", clk->name, clk->clkdm->name, ret);
- goto oce_err2;
- }
- }
-
if (clk->ops && clk->ops->enable) {
trace_clock_enable(clk->name, 1, smp_processor_id());
ret = clk->ops->enable(clk);
if (ret) {
WARN(1, "clock: %s: could not enable: %d\n",
clk->name, ret);
- goto oce_err3;
+ goto oce_err2;
}
}
return 0;
-oce_err3:
- if (clk->clkdm)
- clkdm_clk_disable(clk->clkdm, clk);
oce_err2:
if (clk->parent)
omap2_clk_disable(clk->parent);
@@ -101,14 +101,7 @@ static int omap4_clkdm_is_idle(struct clockdomain *clkdm)
static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
{
- bool hwsup = false;
-
- hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
- clkdm->cm_inst, clkdm->clkdm_offs);
-
- if (!hwsup)
- clkdm_wakeup(clkdm);
-
+ clkdm_wakeup(clkdm);
return 0;
}
@@ -1360,6 +1360,7 @@ static int _reset(struct omap_hwmod *oh)
static int _enable(struct omap_hwmod *oh)
{
int r;
+ int hwsup = 0;
if (oh->_state != _HWMOD_STATE_INITIALIZED &&
oh->_state != _HWMOD_STATE_IDLE &&
@@ -1378,6 +1379,19 @@ static int _enable(struct omap_hwmod *oh)
omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
_add_initiator_dep(oh, mpu_oh);
+
+ /*
+ * A clockdomain must be in SW_SUP before enabling completely the
+ * module. The clockdomain can be set in HW_AUTO only when the module
+ * become ready.
+ */
+ hwsup = clkdm_is_idle(oh->clkdm);
+ r = clkdm_hwmod_enable(oh->clkdm, oh);
+ if (r) {
+ WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
+ oh->name, oh->clkdm->name, r);
+ return r;
+ }
_enable_clocks(oh);
_enable_module(oh);
@@ -1392,6 +1406,13 @@ static int _enable(struct omap_hwmod *oh)
r = _wait_target_ready(oh);
if (!r) {
+ /*
+ * Set the clockdomain to HW_AUTO only if the target is ready,
+ * assuming that the previous state was HW_AUTO
+ */
+ if (hwsup)
+ clkdm_allow_idle(oh->clkdm);
+
oh->_state = _HWMOD_STATE_ENABLED;
/* Access the sysconfig only if the target is ready */
@@ -1402,8 +1423,9 @@ static int _enable(struct omap_hwmod *oh)
}
} else {
_disable_clocks(oh);
- pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
- oh->name, r);
+ clkdm_hwmod_disable(oh->clkdm, oh);
+ pr_warning("omap_hwmod: %s: _wait_target_ready failed: %d\n",
+ oh->name, r);
}
return r;
@@ -1444,6 +1466,7 @@ static int _idle(struct omap_hwmod *oh)
* transition to complete properly.
*/
_disable_clocks(oh);
+ clkdm_hwmod_disable(oh->clkdm, oh);
/* Mux pins for device idle if populated */
if (oh->mux && oh->mux->pads_dynamic)
@@ -1541,6 +1564,7 @@ static int _shutdown(struct omap_hwmod *oh)
pr_warning("omap_hwmod: %s: _wait_target_disable failed\n",
oh->name);
_disable_clocks(oh);
+ clkdm_hwmod_disable(oh->clkdm, oh);
}
/* XXX Should this code also force-disable the optional clocks? */