|
@@ -797,3 +797,76 @@ int clkdm_wakeup(struct clockdomain *clkdm)
|
|
|
pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
|
|
|
|
|
|
spin_lock_irqsave(&clkdm->lock, flags);
|
|
|
+ clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
|
|
|
+ ret = arch_clkdm->clkdm_wakeup(clkdm);
|
|
|
+ ret |= pwrdm_state_switch(clkdm->pwrdm.ptr);
|
|
|
+ spin_unlock_irqrestore(&clkdm->lock, flags);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * clkdm_allow_idle - enable hwsup idle transitions for clkdm
|
|
|
+ * @clkdm: struct clockdomain *
|
|
|
+ *
|
|
|
+ * Allow the hardware to automatically switch the clockdomain @clkdm into
|
|
|
+ * active or idle states, as needed by downstream clocks. If the
|
|
|
+ * clockdomain has any downstream clocks enabled in the clock
|
|
|
+ * framework, wkdep/sleepdep autodependencies are added; this is so
|
|
|
+ * device drivers can read and write to the device. No return value.
|
|
|
+ */
|
|
|
+void clkdm_allow_idle(struct clockdomain *clkdm)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (!clkdm)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) {
|
|
|
+ pr_debug("clock: %s: automatic idle transitions cannot be enabled\n",
|
|
|
+ clkdm->name);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle)
|
|
|
+ return;
|
|
|
+
|
|
|
+ pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
|
|
|
+ clkdm->name);
|
|
|
+
|
|
|
+ spin_lock_irqsave(&clkdm->lock, flags);
|
|
|
+ clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
|
|
|
+ arch_clkdm->clkdm_allow_idle(clkdm);
|
|
|
+ pwrdm_state_switch(clkdm->pwrdm.ptr);
|
|
|
+ spin_unlock_irqrestore(&clkdm->lock, flags);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * clkdm_deny_idle - disable hwsup idle transitions for clkdm
|
|
|
+ * @clkdm: struct clockdomain *
|
|
|
+ *
|
|
|
+ * Prevent the hardware from automatically switching the clockdomain
|
|
|
+ * @clkdm into inactive or idle states. If the clockdomain has
|
|
|
+ * downstream clocks enabled in the clock framework, wkdep/sleepdep
|
|
|
+ * autodependencies are removed. No return value.
|
|
|
+ */
|
|
|
+void clkdm_deny_idle(struct clockdomain *clkdm)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (!clkdm)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) {
|
|
|
+ pr_debug("clockdomain: %s: automatic idle transitions cannot be disabled\n",
|
|
|
+ clkdm->name);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle)
|
|
|
+ return;
|
|
|
+
|
|
|
+ pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
|
|
|
+ clkdm->name);
|
|
|
+
|
|
|
+ spin_lock_irqsave(&clkdm->lock, flags);
|
|
|
+ clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
|