]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
Merge branch 'packaging' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek...
[karo-tx-linux.git] / arch / arm / mach-omap2 / clockdomain2xxx_3xxx.c
index a1fd6fd5a4667a7c5bcab334ca40186009a341d2..48d0db7e6069c90eff01a245153dba465b562b27 100644 (file)
@@ -20,6 +20,7 @@
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
+#include "prm-regbits-24xx.h"
 #include "clockdomain.h"
 
 static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
@@ -111,11 +112,148 @@ static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
        return 0;
 }
 
+static int omap2_clkdm_sleep(struct clockdomain *clkdm)
+{
+       omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+                               clkdm->pwrdm.ptr->prcm_offs,
+                               OMAP2_PM_PWSTCTRL);
+       return 0;
+}
+
+static int omap2_clkdm_wakeup(struct clockdomain *clkdm)
+{
+       omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+                               clkdm->pwrdm.ptr->prcm_offs,
+                               OMAP2_PM_PWSTCTRL);
+       return 0;
+}
+
+static void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+       if (atomic_read(&clkdm->usecount) > 0)
+               _clkdm_add_autodeps(clkdm);
+
+       omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+}
+
+static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+       omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+
+       if (atomic_read(&clkdm->usecount) > 0)
+               _clkdm_del_autodeps(clkdm);
+}
+
+static void _enable_hwsup(struct clockdomain *clkdm)
+{
+       if (cpu_is_omap24xx())
+               omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                                              clkdm->clktrctrl_mask);
+       else if (cpu_is_omap34xx())
+               omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                                              clkdm->clktrctrl_mask);
+}
+
+static void _disable_hwsup(struct clockdomain *clkdm)
+{
+       if (cpu_is_omap24xx())
+               omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                                               clkdm->clktrctrl_mask);
+       else if (cpu_is_omap34xx())
+               omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                                               clkdm->clktrctrl_mask);
+}
+
+
+static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+       bool hwsup = false;
+
+       if (!clkdm->clktrctrl_mask)
+               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 {
+               clkdm_wakeup(clkdm);
+       }
+
+       return 0;
+}
+
+static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+       bool hwsup = false;
+
+       if (!clkdm->clktrctrl_mask)
+               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_del_autodeps(clkdm);
+               _enable_hwsup(clkdm);
+       } else {
+               clkdm_sleep(clkdm);
+       }
+
+       return 0;
+}
+
+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 void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+       if (atomic_read(&clkdm->usecount) > 0)
+               _clkdm_add_autodeps(clkdm);
+
+       omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+}
+
+static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+       omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+
+       if (atomic_read(&clkdm->usecount) > 0)
+               _clkdm_del_autodeps(clkdm);
+}
+
 struct clkdm_ops omap2_clkdm_operations = {
        .clkdm_add_wkdep        = omap2_clkdm_add_wkdep,
        .clkdm_del_wkdep        = omap2_clkdm_del_wkdep,
        .clkdm_read_wkdep       = omap2_clkdm_read_wkdep,
        .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
+       .clkdm_sleep            = omap2_clkdm_sleep,
+       .clkdm_wakeup           = omap2_clkdm_wakeup,
+       .clkdm_allow_idle       = omap2_clkdm_allow_idle,
+       .clkdm_deny_idle        = omap2_clkdm_deny_idle,
+       .clkdm_clk_enable       = omap2_clkdm_clk_enable,
+       .clkdm_clk_disable      = omap2_clkdm_clk_disable,
 };
 
 struct clkdm_ops omap3_clkdm_operations = {
@@ -127,4 +265,10 @@ struct clkdm_ops omap3_clkdm_operations = {
        .clkdm_del_sleepdep     = omap3_clkdm_del_sleepdep,
        .clkdm_read_sleepdep    = omap3_clkdm_read_sleepdep,
        .clkdm_clear_all_sleepdeps      = omap3_clkdm_clear_all_sleepdeps,
+       .clkdm_sleep            = omap3_clkdm_sleep,
+       .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,
 };