]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - sitara-epos/sitara-epos-kernel.git/blob - arch/arm/mach-omap2/powerdomain33xx.c
arm: am33xx: Add CPSW MII mac select support
[sitara-epos/sitara-epos-kernel.git] / arch / arm / mach-omap2 / powerdomain33xx.c
1 /*
2  * AM33XX Powerdomain control
3  *
4  * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation version 2.
9  *
10  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11  * kind, whether express or implied; without even the implied warranty
12  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
16 #include <linux/io.h>
17 #include <linux/errno.h>
18 #include <linux/delay.h>
20 #include <plat/prcm.h>
22 #include "powerdomain.h"
23 #include "prm33xx.h"
24 #include "prm-regbits-33xx.h"
25 #include "prminst33xx.h"
28 static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
29 {
30         am33xx_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
31                                         (pwrst << OMAP_POWERSTATE_SHIFT),
32                                         pwrdm->prcm_offs, AM33XX_PM_PWSTCTRL);
33         return 0;
34 }
36 static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
37 {
38         u32 v;
40         v = am33xx_prminst_read_inst_reg(pwrdm->prcm_offs, AM33XX_PM_PWSTCTRL);
41         v &= OMAP_POWERSTATE_MASK;
42         v >>= OMAP_POWERSTATE_SHIFT;
44         return v;
45 }
47 static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
48 {
49         u32 v;
51         v = am33xx_prminst_read_inst_reg(pwrdm->prcm_offs, AM33XX_PM_PWSTST);
52         v &= OMAP_POWERSTATEST_MASK;
53         v >>= OMAP_POWERSTATEST_SHIFT;
55         return v;
56 }
58 static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
59 {
60         u32 v;
62         v = am33xx_prminst_read_inst_reg(pwrdm->prcm_offs, AM33XX_PM_PWSTST);
63         v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
64         v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
66         return v;
67 }
69 static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
70 {
71         am33xx_prminst_rmw_inst_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
72                         (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
73                         pwrdm->prcm_offs, AM33XX_PM_PWSTCTRL);
74         return 0;
75 }
77 static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
78 {
79         am33xx_prminst_rmw_inst_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
80                         AM33XX_LASTPOWERSTATEENTERED_MASK,
81                         pwrdm->prcm_offs, AM33XX_PM_PWSTST);
82         return 0;
83 }
85 static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
86 {
87         u32 v;
89         v = pwrst << __ffs(AM33XX_LOGICRETSTATE_MASK);
90         am33xx_prminst_rmw_inst_reg_bits(AM33XX_LOGICRETSTATE_MASK, v,
91                         pwrdm->prcm_offs, AM33XX_PM_PWSTCTRL);
93         return 0;
94 }
96 static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
97 {
98         u32 v;
100         v = am33xx_prminst_read_inst_reg(pwrdm->prcm_offs, AM33XX_PM_PWSTST);
101         v &= AM33XX_LOGICSTATEST_MASK;
102         v >>= AM33XX_LOGICSTATEST_SHIFT;
104         return v;
107 static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
109         u32 v;
111         v = am33xx_prminst_read_inst_reg(pwrdm->prcm_offs, AM33XX_PM_PWSTCTRL);
112         v &= AM33XX_LOGICRETSTATE_MASK;
113         v >>= AM33XX_LOGICRETSTATE_SHIFT;
115         return v;
118 static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
120         u32 c = 0;
122         /*
123          * REVISIT: pwrdm_wait_transition() may be better implemented
124          * via a callback and a periodic timer check -- how long do we expect
125          * powerdomain transitions to take?
126          */
128         /* XXX Is this udelay() value meaningful? */
129         while ((am33xx_prminst_read_inst_reg(pwrdm->prcm_offs, AM33XX_PM_PWSTST)
130                 & OMAP_INTRANSITION_MASK) && (c++ < PWRDM_TRANSITION_BAILOUT))
131                 udelay(1);
133         if (c > PWRDM_TRANSITION_BAILOUT) {
134                 printk(KERN_ERR "powerdomain: waited too long for "
135                         "powerdomain %s to complete transition\n", pwrdm->name);
136                 return -EAGAIN;
137         }
139         pr_debug("powerdomain: completed transition in %d loops\n", c);
141         return 0;
144 struct pwrdm_ops am33xx_pwrdm_operations = {
145         .pwrdm_set_next_pwrst           = am33xx_pwrdm_set_next_pwrst,
146         .pwrdm_read_next_pwrst          = am33xx_pwrdm_read_next_pwrst,
147         .pwrdm_read_pwrst               = am33xx_pwrdm_read_pwrst,
148         .pwrdm_read_prev_pwrst          = am33xx_pwrdm_read_prev_pwrst,
149         .pwrdm_set_logic_retst          = am33xx_pwrdm_set_logic_retst,
150         .pwrdm_read_logic_pwrst         = am33xx_pwrdm_read_logic_pwrst,
151         .pwrdm_read_logic_retst         = am33xx_pwrdm_read_logic_retst,
152         .pwrdm_clear_all_prev_pwrst     = am33xx_pwrdm_clear_all_prev_pwrst,
153         .pwrdm_set_lowpwrstchange       = am33xx_pwrdm_set_lowpwrstchange,
154         .pwrdm_wait_transition          = am33xx_pwrdm_wait_transition,
155 };