aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/pm34xx.c
diff options
context:
space:
mode:
authorRajendra Nayak <rnayak@ti.com>2008-09-26 08:19:22 -0400
committerKevin Hilman <khilman@deeprootsystems.com>2009-11-11 17:42:24 -0500
commitfa3c2a4fc99fd7f8c245020303d7e11feadbbac9 (patch)
treedc689a1dfef10dd4d1595a6ad1e0edaccb88ea5f /arch/arm/mach-omap2/pm34xx.c
parent3231fc889c114870ca830041fcdeb5d4745304cf (diff)
OMAP3: PM: handle PER/NEON/CORE in idle
Expand the powerdomains handled in the idle path to include PER, NEON and CORE. This includes properly clearing the previous powerstates, linking NEON state to MPU state and calling the UART prepare functions for only the appropraite powerdomain transitions (CORE for UART1,2, PER for UART3.) Signed-off-by: Rajendra Nayak <rnayak@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-omap2/pm34xx.c')
-rw-r--r--arch/arm/mach-omap2/pm34xx.c64
1 files changed, 54 insertions, 10 deletions
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index b88da1bcb66c..05ee05f012ad 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -49,7 +49,10 @@ static LIST_HEAD(pwrst_list);
49 49
50static void (*_omap_sram_idle)(u32 *addr, int save_state); 50static void (*_omap_sram_idle)(u32 *addr, int save_state);
51 51
52static struct powerdomain *mpu_pwrdm; 52static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
53static struct powerdomain *core_pwrdm, *per_pwrdm;
54
55static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
53 56
54/* 57/*
55 * PRCM Interrupt Handler Helper Function 58 * PRCM Interrupt Handler Helper Function
@@ -169,13 +172,22 @@ static void omap_sram_idle(void)
169 /* save_state = 1 => Only L1 and logic lost */ 172 /* save_state = 1 => Only L1 and logic lost */
170 /* save_state = 2 => Only L2 lost */ 173 /* save_state = 2 => Only L2 lost */
171 /* save_state = 3 => L1, L2 and logic lost */ 174 /* save_state = 3 => L1, L2 and logic lost */
172 int save_state = 0, mpu_next_state; 175 int save_state = 0;
176 int mpu_next_state = PWRDM_POWER_ON;
177 int per_next_state = PWRDM_POWER_ON;
178 int core_next_state = PWRDM_POWER_ON;
173 179
174 if (!_omap_sram_idle) 180 if (!_omap_sram_idle)
175 return; 181 return;
176 182
183 pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
184 pwrdm_clear_all_prev_pwrst(neon_pwrdm);
185 pwrdm_clear_all_prev_pwrst(core_pwrdm);
186 pwrdm_clear_all_prev_pwrst(per_pwrdm);
187
177 mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); 188 mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
178 switch (mpu_next_state) { 189 switch (mpu_next_state) {
190 case PWRDM_POWER_ON:
179 case PWRDM_POWER_RET: 191 case PWRDM_POWER_RET:
180 /* No need to save context */ 192 /* No need to save context */
181 save_state = 0; 193 save_state = 0;
@@ -187,18 +199,37 @@ static void omap_sram_idle(void)
187 } 199 }
188 pwrdm_pre_transition(); 200 pwrdm_pre_transition();
189 201
190 omap2_gpio_prepare_for_retention(); 202 /* NEON control */
191 omap_uart_prepare_idle(0); 203 if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
192 omap_uart_prepare_idle(1); 204 set_pwrdm_state(neon_pwrdm, mpu_next_state);
193 omap_uart_prepare_idle(2); 205
206 /* CORE & PER */
207 core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
208 if (core_next_state < PWRDM_POWER_ON) {
209 omap2_gpio_prepare_for_retention();
210 omap_uart_prepare_idle(0);
211 omap_uart_prepare_idle(1);
212 /* PER changes only with core */
213 per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
214 if (per_next_state < PWRDM_POWER_ON)
215 omap_uart_prepare_idle(2);
216 /* Enable IO-PAD wakeup */
217 prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
218 }
194 219
195 _omap_sram_idle(NULL, save_state); 220 _omap_sram_idle(NULL, save_state);
196 cpu_init(); 221 cpu_init();
197 222
198 omap_uart_resume_idle(2); 223 if (core_next_state < PWRDM_POWER_ON) {
199 omap_uart_resume_idle(1); 224 if (per_next_state < PWRDM_POWER_ON)
200 omap_uart_resume_idle(0); 225 omap_uart_resume_idle(2);
201 omap2_gpio_resume_after_retention(); 226 omap_uart_resume_idle(1);
227 omap_uart_resume_idle(0);
228
229 /* Disable IO-PAD wakeup */
230 prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
231 omap2_gpio_resume_after_retention();
232 }
202 233
203 pwrdm_post_transition(); 234 pwrdm_post_transition();
204 235
@@ -792,6 +823,10 @@ static int __init omap3_pm_init(void)
792 goto err2; 823 goto err2;
793 } 824 }
794 825
826 neon_pwrdm = pwrdm_lookup("neon_pwrdm");
827 per_pwrdm = pwrdm_lookup("per_pwrdm");
828 core_pwrdm = pwrdm_lookup("core_pwrdm");
829
795 omap_push_sram_idle(); 830 omap_push_sram_idle();
796#ifdef CONFIG_SUSPEND 831#ifdef CONFIG_SUSPEND
797 suspend_set_ops(&omap_pm_ops); 832 suspend_set_ops(&omap_pm_ops);
@@ -799,6 +834,15 @@ static int __init omap3_pm_init(void)
799 834
800 pm_idle = omap3_pm_idle; 835 pm_idle = omap3_pm_idle;
801 836
837 pwrdm_add_wkdep(neon_pwrdm, mpu_pwrdm);
838 /*
839 * REVISIT: This wkdep is only necessary when GPIO2-6 are enabled for
840 * IO-pad wakeup. Otherwise it will unnecessarily waste power
841 * waking up PER with every CORE wakeup - see
842 * http://marc.info/?l=linux-omap&m=121852150710062&w=2
843 */
844 pwrdm_add_wkdep(per_pwrdm, core_pwrdm);
845
802err1: 846err1:
803 return ret; 847 return ret;
804err2: 848err2: