summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/clockdomain2xxx_3xxx.c')
-rw-r--r--arch/arm/mach-omap2/clockdomain2xxx_3xxx.c97
1 files changed, 82 insertions, 15 deletions
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
index a0d68dbecfa3..70294f54e35a 100644
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -162,6 +162,19 @@ static void _disable_hwsup(struct clockdomain *clkdm)
clkdm->clktrctrl_mask);
}
+static int omap3_clkdm_sleep(struct clockdomain *clkdm)
+{
+ omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+ clkdm->clktrctrl_mask);
+ return 0;
+}
+
+static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
+{
+ omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+ clkdm->clktrctrl_mask);
+ return 0;
+}
static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
{
@@ -209,36 +222,90 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
return 0;
}
-static int omap3_clkdm_sleep(struct clockdomain *clkdm)
+static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
{
- omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+ if (atomic_read(&clkdm->usecount) > 0)
+ _clkdm_add_autodeps(clkdm);
+
+ omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
clkdm->clktrctrl_mask);
- return 0;
}
-static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
+static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
{
- omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+ omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
clkdm->clktrctrl_mask);
- return 0;
+
+ if (atomic_read(&clkdm->usecount) > 0)
+ _clkdm_del_autodeps(clkdm);
}
-static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
+static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
{
- if (atomic_read(&clkdm->usecount) > 0)
- _clkdm_add_autodeps(clkdm);
+ bool hwsup = false;
- omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+ if (!clkdm->clktrctrl_mask)
+ return 0;
+
+ /*
+ * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+ * more details on the unpleasant problem this is working
+ * around
+ */
+ if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
+ (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
+ omap3_clkdm_wakeup(clkdm);
+ return 0;
+ }
+
+ hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
clkdm->clktrctrl_mask);
+
+ if (hwsup) {
+ /* Disable HW transitions when we are changing deps */
+ _disable_hwsup(clkdm);
+ _clkdm_add_autodeps(clkdm);
+ _enable_hwsup(clkdm);
+ } else {
+ if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+ omap3_clkdm_wakeup(clkdm);
+ }
+
+ return 0;
}
-static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
+static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
{
- omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+ bool hwsup = false;
+
+ if (!clkdm->clktrctrl_mask)
+ return 0;
+
+ /*
+ * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+ * more details on the unpleasant problem this is working
+ * around
+ */
+ if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
+ !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
+ _enable_hwsup(clkdm);
+ return 0;
+ }
+
+ hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
clkdm->clktrctrl_mask);
- if (atomic_read(&clkdm->usecount) > 0)
+ if (hwsup) {
+ /* Disable HW transitions when we are changing deps */
+ _disable_hwsup(clkdm);
_clkdm_del_autodeps(clkdm);
+ _enable_hwsup(clkdm);
+ } else {
+ if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+ omap3_clkdm_sleep(clkdm);
+ }
+
+ return 0;
}
struct clkdm_ops omap2_clkdm_operations = {
@@ -267,6 +334,6 @@ struct clkdm_ops omap3_clkdm_operations = {
.clkdm_wakeup = omap3_clkdm_wakeup,
.clkdm_allow_idle = omap3_clkdm_allow_idle,
.clkdm_deny_idle = omap3_clkdm_deny_idle,
- .clkdm_clk_enable = omap2_clkdm_clk_enable,
- .clkdm_clk_disable = omap2_clkdm_clk_disable,
+ .clkdm_clk_enable = omap3xxx_clkdm_clk_enable,
+ .clkdm_clk_disable = omap3xxx_clkdm_clk_disable,
};