]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/arm/mach-omap2/powerdomain44xx.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / arch / arm / mach-omap2 / powerdomain44xx.c
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
new file mode 100644 (file)
index 0000000..a7880af
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * OMAP4 powerdomain control
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Nokia Corporation
+ *
+ * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include "powerdomain.h"
+#include <plat/prcm.h>
+#include "prm2xxx_3xxx.h"
+#include "prm44xx.h"
+#include "prminst44xx.h"
+#include "prm-regbits-44xx.h"
+
+static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+       omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
+                                       (pwrst << OMAP_POWERSTATE_SHIFT),
+                                       pwrdm->prcm_partition,
+                                       pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
+       return 0;
+}
+
+static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTCTRL);
+       v &= OMAP_POWERSTATE_MASK;
+       v >>= OMAP_POWERSTATE_SHIFT;
+
+       return v;
+}
+
+static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTST);
+       v &= OMAP_POWERSTATEST_MASK;
+       v >>= OMAP_POWERSTATEST_SHIFT;
+
+       return v;
+}
+
+static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTST);
+       v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
+       v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
+
+       return v;
+}
+
+static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
+{
+       omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
+                                       (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
+                                       pwrdm->prcm_partition,
+                                       pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
+       return 0;
+}
+
+static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+       omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
+                                       OMAP4430_LASTPOWERSTATEENTERED_MASK,
+                                       pwrdm->prcm_partition,
+                                       pwrdm->prcm_offs, OMAP4_PM_PWSTST);
+       return 0;
+}
+
+static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
+{
+       u32 v;
+
+       v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
+       omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
+                                       pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTCTRL);
+
+       return 0;
+}
+
+static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+                                   u8 pwrst)
+{
+       u32 m;
+
+       m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
+
+       omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
+                                       pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTCTRL);
+
+       return 0;
+}
+
+static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+                                    u8 pwrst)
+{
+       u32 m;
+
+       m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
+
+       omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
+                                       pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTCTRL);
+
+       return 0;
+}
+
+static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTST);
+       v &= OMAP4430_LOGICSTATEST_MASK;
+       v >>= OMAP4430_LOGICSTATEST_SHIFT;
+
+       return v;
+}
+
+static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTCTRL);
+       v &= OMAP4430_LOGICRETSTATE_MASK;
+       v >>= OMAP4430_LOGICRETSTATE_SHIFT;
+
+       return v;
+}
+
+static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+       u32 m, v;
+
+       m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
+
+       v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTST);
+       v &= m;
+       v >>= __ffs(m);
+
+       return v;
+}
+
+static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
+{
+       u32 m, v;
+
+       m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
+
+       v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+                                       OMAP4_PM_PWSTCTRL);
+       v &= m;
+       v >>= __ffs(m);
+
+       return v;
+}
+
+static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
+{
+       u32 c = 0;
+
+       /*
+        * REVISIT: pwrdm_wait_transition() may be better implemented
+        * via a callback and a periodic timer check -- how long do we expect
+        * powerdomain transitions to take?
+        */
+
+       /* XXX Is this udelay() value meaningful? */
+       while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
+                                           pwrdm->prcm_offs,
+                                           OMAP4_PM_PWSTST) &
+               OMAP_INTRANSITION_MASK) &&
+              (c++ < PWRDM_TRANSITION_BAILOUT))
+               udelay(1);
+
+       if (c > PWRDM_TRANSITION_BAILOUT) {
+               printk(KERN_ERR "powerdomain: waited too long for "
+                      "powerdomain %s to complete transition\n", pwrdm->name);
+               return -EAGAIN;
+       }
+
+       pr_debug("powerdomain: completed transition in %d loops\n", c);
+
+       return 0;
+}
+
+struct pwrdm_ops omap4_pwrdm_operations = {
+       .pwrdm_set_next_pwrst   = omap4_pwrdm_set_next_pwrst,
+       .pwrdm_read_next_pwrst  = omap4_pwrdm_read_next_pwrst,
+       .pwrdm_read_pwrst       = omap4_pwrdm_read_pwrst,
+       .pwrdm_read_prev_pwrst  = omap4_pwrdm_read_prev_pwrst,
+       .pwrdm_set_lowpwrstchange       = omap4_pwrdm_set_lowpwrstchange,
+       .pwrdm_clear_all_prev_pwrst     = omap4_pwrdm_clear_all_prev_pwrst,
+       .pwrdm_set_logic_retst  = omap4_pwrdm_set_logic_retst,
+       .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
+       .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
+       .pwrdm_read_mem_pwrst   = omap4_pwrdm_read_mem_pwrst,
+       .pwrdm_read_mem_retst   = omap4_pwrdm_read_mem_retst,
+       .pwrdm_set_mem_onst     = omap4_pwrdm_set_mem_onst,
+       .pwrdm_set_mem_retst    = omap4_pwrdm_set_mem_retst,
+       .pwrdm_wait_transition  = omap4_pwrdm_wait_transition,
+};