Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec...
[pandora-kernel.git] / arch / arm / mach-omap2 / clockdomain.c
index 6fb61b1..e20b986 100644 (file)
@@ -13,7 +13,6 @@
  */
 #undef DEBUG
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/list.h>
 
 #include <linux/bitops.h>
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "cminst44xx.h"
+#include "prcm44xx.h"
 
 #include <plat/clock.h>
-#include <plat/powerdomain.h>
-#include <plat/clockdomain.h>
+#include "powerdomain.h"
+#include "clockdomain.h"
 #include <plat/prcm.h>
 
 /* clkdm_list contains all registered struct clockdomains */
@@ -141,6 +143,9 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
  * clockdomain is in hardware-supervised mode. Meant to be called
  * once at clockdomain layer initialization, since these should remain
  * fixed for a particular architecture.  No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
  */
 static void _autodep_lookup(struct clkdm_autodep *autodep)
 {
@@ -168,6 +173,9 @@ static void _autodep_lookup(struct clkdm_autodep *autodep)
  * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
  * in hardware-supervised mode.  Meant to be called from clock framework
  * when a clock inside clockdomain 'clkdm' is enabled. No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
  */
 static void _clkdm_add_autodeps(struct clockdomain *clkdm)
 {
@@ -199,6 +207,9 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm)
  * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
  * in hardware-supervised mode.  Meant to be called from clock framework
  * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
  */
 static void _clkdm_del_autodeps(struct clockdomain *clkdm)
 {
@@ -223,39 +234,56 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm)
        }
 }
 
-/*
- * _omap2_clkdm_set_hwsup - set the hwsup idle transition bit
+/**
+ * _enable_hwsup - place a clockdomain into hardware-supervised idle
  * @clkdm: struct clockdomain *
- * @enable: int 0 to disable, 1 to enable
  *
- * Internal helper for actually switching the bit that controls hwsup
- * idle transitions for clkdm.
+ * Place the clockdomain into hardware-supervised idle mode.  No return
+ * value.
+ *
+ * XXX Should this return an error if the clockdomain does not support
+ * hardware-supervised idle mode?
  */
-static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
+static void _enable_hwsup(struct clockdomain *clkdm)
 {
-       u32 bits, v;
-
-       if (cpu_is_omap24xx()) {
-               if (enable)
-                       bits = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
-               else
-                       bits = OMAP24XX_CLKSTCTRL_DISABLE_AUTO;
-       } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-               if (enable)
-                       bits = OMAP34XX_CLKSTCTRL_ENABLE_AUTO;
-               else
-                       bits = OMAP34XX_CLKSTCTRL_DISABLE_AUTO;
-       } else {
+       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);
+       else if (cpu_is_omap44xx())
+               return omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
+                                                      clkdm->cm_inst,
+                                                      clkdm->clkdm_offs);
+       else
                BUG();
-       }
-
-       bits = bits << __ffs(clkdm->clktrctrl_mask);
-
-       v = __raw_readl(clkdm->clkstctrl_reg);
-       v &= ~(clkdm->clktrctrl_mask);
-       v |= bits;
-       __raw_writel(v, clkdm->clkstctrl_reg);
+}
 
+/**
+ * _disable_hwsup - place a clockdomain into software-supervised idle
+ * @clkdm: struct clockdomain *
+ *
+ * Place the clockdomain @clkdm into software-supervised idle mode.
+ * No return value.
+ *
+ * XXX Should this return an error if the clockdomain does not support
+ * software-supervised idle mode?
+ */
+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);
+       else if (cpu_is_omap44xx())
+               return omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
+                                                       clkdm->cm_inst,
+                                                       clkdm->clkdm_offs);
+       else
+               BUG();
 }
 
 /* Public functions */
@@ -409,7 +437,7 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
                pr_debug("clockdomain: hardware will wake up %s when %s wakes "
                         "up\n", clkdm1->name, clkdm2->name);
 
-               prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+               omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
                                     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
        }
 
@@ -444,7 +472,7 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
                pr_debug("clockdomain: hardware will no longer wake up %s "
                         "after %s wakes up\n", clkdm1->name, clkdm2->name);
 
-               prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+               omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
                                       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
        }
 
@@ -480,7 +508,7 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
        }
 
        /* XXX It's faster to return the atomic wkdep_usecount */
-       return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
+       return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
                                       (1 << clkdm2->dep_bit));
 }
 
@@ -514,7 +542,7 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
                atomic_set(&cd->wkdep_usecount, 0);
        }
 
-       prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
+       omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
 
        return 0;
 }
@@ -553,7 +581,7 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
                pr_debug("clockdomain: will prevent %s from sleeping if %s "
                         "is active\n", clkdm1->name, clkdm2->name);
 
-               cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+               omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
                                    clkdm1->pwrdm.ptr->prcm_offs,
                                    OMAP3430_CM_SLEEPDEP);
        }
@@ -596,7 +624,7 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
                         "sleeping if %s is active\n", clkdm1->name,
                         clkdm2->name);
 
-               cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+               omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
                                      clkdm1->pwrdm.ptr->prcm_offs,
                                      OMAP3430_CM_SLEEPDEP);
        }
@@ -639,7 +667,7 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
        }
 
        /* XXX It's faster to return the atomic sleepdep_usecount */
-       return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+       return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
                                       OMAP3430_CM_SLEEPDEP,
                                       (1 << clkdm2->dep_bit));
 }
@@ -677,34 +705,12 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
                atomic_set(&cd->sleepdep_usecount, 0);
        }
 
-       prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+       omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
                               OMAP3430_CM_SLEEPDEP);
 
        return 0;
 }
 
-/**
- * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
- * @clkdm: struct clkdm * of a clockdomain
- *
- * Return the clockdomain @clkdm current state transition mode from the
- * corresponding domain CM_CLKSTCTRL register. Returns -EINVAL if @clkdm
- * is NULL or the current mode upon success.
- */
-static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm)
-{
-       u32 v;
-
-       if (!clkdm)
-               return -EINVAL;
-
-       v = __raw_readl(clkdm->clkstctrl_reg);
-       v &= clkdm->clktrctrl_mask;
-       v >>= __ffs(clkdm->clktrctrl_mask);
-
-       return v;
-}
-
 /**
  * omap2_clkdm_sleep - force clockdomain sleep transition
  * @clkdm: struct clockdomain *
@@ -729,18 +735,19 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm)
 
        if (cpu_is_omap24xx()) {
 
-               cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+               omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
                            clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
 
-       } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+       } else if (cpu_is_omap34xx()) {
+
+               omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+                                             clkdm->clktrctrl_mask);
 
-               u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP <<
-                        __ffs(clkdm->clktrctrl_mask));
+       } else if (cpu_is_omap44xx()) {
 
-               u32 v = __raw_readl(clkdm->clkstctrl_reg);
-               v &= ~(clkdm->clktrctrl_mask);
-               v |= bits;
-               __raw_writel(v, clkdm->clkstctrl_reg);
+               omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
+                                              clkdm->cm_inst,
+                                              clkdm->clkdm_offs);
 
        } else {
                BUG();
@@ -773,18 +780,19 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
 
        if (cpu_is_omap24xx()) {
 
-               cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+               omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
                              clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
 
-       } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+       } else if (cpu_is_omap34xx()) {
 
-               u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP <<
-                        __ffs(clkdm->clktrctrl_mask));
+               omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+                                              clkdm->clktrctrl_mask);
 
-               u32 v = __raw_readl(clkdm->clkstctrl_reg);
-               v &= ~(clkdm->clktrctrl_mask);
-               v |= bits;
-               __raw_writel(v, clkdm->clkstctrl_reg);
+       } else if (cpu_is_omap44xx()) {
+
+               omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
+                                               clkdm->cm_inst,
+                                               clkdm->clkdm_offs);
 
        } else {
                BUG();
@@ -829,7 +837,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
                        _clkdm_add_autodeps(clkdm);
        }
 
-       _omap2_clkdm_set_hwsup(clkdm, 1);
+       _enable_hwsup(clkdm);
 
        pwrdm_clkdm_state_switch(clkdm);
 }
@@ -857,7 +865,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
        pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
                 clkdm->name);
 
-       _omap2_clkdm_set_hwsup(clkdm, 0);
+       _disable_hwsup(clkdm);
 
        /*
         * XXX This should be removed once TI adds wakeup/sleep
@@ -891,7 +899,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
  */
 int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 {
-       int v;
+       bool hwsup = false;
 
        /*
         * XXX Rewrite this code to maintain a list of enabled
@@ -909,17 +917,27 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
        pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
                 clk->name);
 
-       if (!clkdm->clkstctrl_reg)
-               return 0;
+       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
 
-       v = omap2_clkdm_clktrctrl_read(clkdm);
+               if (!clkdm->clktrctrl_mask)
+                       return 0;
 
-       if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
-           (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) {
+               hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                                                  clkdm->clktrctrl_mask);
+
+       } else if (cpu_is_omap44xx()) {
+
+               hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+                                                      clkdm->cm_inst,
+                                                      clkdm->clkdm_offs);
+
+       }
+
+       if (hwsup) {
                /* Disable HW transitions when we are changing deps */
-               _omap2_clkdm_set_hwsup(clkdm, 0);
+               _disable_hwsup(clkdm);
                _clkdm_add_autodeps(clkdm);
-               _omap2_clkdm_set_hwsup(clkdm, 1);
+               _enable_hwsup(clkdm);
        } else {
                omap2_clkdm_wakeup(clkdm);
        }
@@ -946,7 +964,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
  */
 int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
-       int v;
+       bool hwsup = false;
 
        /*
         * XXX Rewrite this code to maintain a list of enabled
@@ -971,17 +989,27 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
        pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
                 clk->name);
 
-       if (!clkdm->clkstctrl_reg)
-               return 0;
+       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
 
-       v = omap2_clkdm_clktrctrl_read(clkdm);
+               if (!clkdm->clktrctrl_mask)
+                       return 0;
+
+               hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                                                  clkdm->clktrctrl_mask);
+
+       } else if (cpu_is_omap44xx()) {
+
+               hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+                                                      clkdm->cm_inst,
+                                                      clkdm->clkdm_offs);
+
+       }
 
-       if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
-           (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) {
+       if (hwsup) {
                /* Disable HW transitions when we are changing deps */
-               _omap2_clkdm_set_hwsup(clkdm, 0);
+               _disable_hwsup(clkdm);
                _clkdm_del_autodeps(clkdm);
-               _omap2_clkdm_set_hwsup(clkdm, 1);
+               _enable_hwsup(clkdm);
        } else {
                omap2_clkdm_sleep(clkdm);
        }