summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/prm33xx.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2012-10-25 02:05:59 +0200
committerTony Lindgren <tony@atomide.com>2012-10-25 02:05:59 +0200
commit8634155ef41d3a035f2ea0b6c5bed2806f2788bc (patch)
tree6334a630abf196685803f17002fbf25d11babe17 /arch/arm/mach-omap2/prm33xx.c
parentMerge branch 'omap-for-v3.8/cleanup-headers-usb' into omap-for-v3.8/cleanup-h... (diff)
parentARM: OMAP2+: PRM: create PRM reset source API for the watchdog timer driver (diff)
downloadlinux-8634155ef41d3a035f2ea0b6c5bed2806f2788bc.tar.xz
linux-8634155ef41d3a035f2ea0b6c5bed2806f2788bc.zip
Merge tag 'omap-cleanup-a-for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into omap-for-v3.8/cleanup-prcm
The first set of OMAP PRM/CM-related cleanup patches for 3.8. Prepares for the future move of the PRM/CM code to drivers/. Also includes some prcm.[ch] cleanup patches from the WDTIMER cleanup series that don't need external acks. Basic test logs for this branch on top of v3.7-rc2 are here: http://www.pwsan.com/omap/testlogs/prcm_cleanup_a_3.8/20121021123719/ But due to the number of unrelated regressions present in v3.7-rc[12], it's not particularly usable as a testing base. With reverts, fixes, and workarounds applied as documented in: http://www.pwsan.com/omap/testlogs/test_v3.7-rc2/20121020134755/README.txt the following test logs were obtained: http://www.pwsan.com/omap/testlogs/prcm_cleanup_a_3.8/20121020231757/ which indicate that the series tests cleanly. Conflicts: arch/arm/mach-omap2/Makefile arch/arm/mach-omap2/clockdomain2xxx_3xxx.c arch/arm/mach-omap2/pm24xx.c
Diffstat (limited to 'arch/arm/mach-omap2/prm33xx.c')
-rw-r--r--arch/arm/mach-omap2/prm33xx.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c
index 624ade5c3c33..53ec9cbaa3d3 100644
--- a/arch/arm/mach-omap2/prm33xx.c
+++ b/arch/arm/mach-omap2/prm33xx.c
@@ -22,6 +22,7 @@
#include "../plat-omap/common.h"
#include "common.h"
+#include "powerdomain.h"
#include "prm33xx.h"
#include "prm-regbits-33xx.h"
@@ -133,3 +134,204 @@ int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
}
+
+static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+ am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
+ (pwrst << OMAP_POWERSTATE_SHIFT),
+ pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+ return 0;
+}
+
+static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+ u32 v;
+
+ v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+ v &= OMAP_POWERSTATE_MASK;
+ v >>= OMAP_POWERSTATE_SHIFT;
+
+ return v;
+}
+
+static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+ u32 v;
+
+ v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+ v &= OMAP_POWERSTATEST_MASK;
+ v >>= OMAP_POWERSTATEST_SHIFT;
+
+ return v;
+}
+
+static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+ u32 v;
+
+ v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+ v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
+ v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
+
+ return v;
+}
+
+static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
+{
+ am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
+ (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
+ pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+ return 0;
+}
+
+static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+ am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
+ AM33XX_LASTPOWERSTATEENTERED_MASK,
+ pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+ return 0;
+}
+
+static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
+{
+ u32 m;
+
+ m = pwrdm->logicretstate_mask;
+ if (!m)
+ return -EINVAL;
+
+ am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+ pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+ return 0;
+}
+
+static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+ u32 v;
+
+ v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+ v &= AM33XX_LOGICSTATEST_MASK;
+ v >>= AM33XX_LOGICSTATEST_SHIFT;
+
+ return v;
+}
+
+static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
+{
+ u32 v, m;
+
+ m = pwrdm->logicretstate_mask;
+ if (!m)
+ return -EINVAL;
+
+ v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+ v &= m;
+ v >>= __ffs(m);
+
+ return v;
+}
+
+static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+ u8 pwrst)
+{
+ u32 m;
+
+ m = pwrdm->mem_on_mask[bank];
+ if (!m)
+ return -EINVAL;
+
+ am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+ pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+ return 0;
+}
+
+static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+ u8 pwrst)
+{
+ u32 m;
+
+ m = pwrdm->mem_ret_mask[bank];
+ if (!m)
+ return -EINVAL;
+
+ am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+ pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+ return 0;
+}
+
+static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+ u32 m, v;
+
+ m = pwrdm->mem_pwrst_mask[bank];
+ if (!m)
+ return -EINVAL;
+
+ v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+ v &= m;
+ v >>= __ffs(m);
+
+ return v;
+}
+
+static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
+{
+ u32 m, v;
+
+ m = pwrdm->mem_retst_mask[bank];
+ if (!m)
+ return -EINVAL;
+
+ v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+ v &= m;
+ v >>= __ffs(m);
+
+ return v;
+}
+
+static int am33xx_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 ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
+ & OMAP_INTRANSITION_MASK) &&
+ (c++ < PWRDM_TRANSITION_BAILOUT))
+ udelay(1);
+
+ if (c > PWRDM_TRANSITION_BAILOUT) {
+ pr_err("powerdomain: %s: waited too long to complete transition\n",
+ pwrdm->name);
+ return -EAGAIN;
+ }
+
+ pr_debug("powerdomain: completed transition in %d loops\n", c);
+
+ return 0;
+}
+
+struct pwrdm_ops am33xx_pwrdm_operations = {
+ .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
+ .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
+ .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
+ .pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
+ .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
+ .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
+ .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
+ .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
+ .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange,
+ .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst,
+ .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst,
+ .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst,
+ .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
+ .pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
+};