aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/pm34xx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 16:46:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 16:46:56 -0400
commit7b6181e06841f5ad15c4ff708b967b4db65a64de (patch)
treebdfcf5b74b692f76581156e452d268b64c795200 /arch/arm/mach-omap2/pm34xx.c
parent72e58063d63c5f0a7bf65312f1e3a5ed9bb5c2ff (diff)
parentbc487fb341af05120bccb9f59ce76302391dcc77 (diff)
Merge branch 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6
* 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6: (163 commits) omap: complete removal of machine_desc.io_pg_offst and .phys_io omap: UART: fix wakeup registers for OMAP24xx UART2 omap: Fix spotty MMC voltages ASoC: OMAP4: MCPDM: Remove unnecessary include of plat/control.h serial: omap-serial: fix signess error OMAP3: DMA: Errata i541: sDMA FIFO draining does not finish omap: dma: Fix buffering disable bit setting for omap24xx omap: serial: Fix the boot-up crash/reboot without CONFIG_PM OMAP3: PM: fix scratchpad memory accesses for off-mode omap4: pandaboard: enable the ehci port on pandaboard omap4: pandaboard: Fix the init if CONFIG_MMC_OMAP_HS is not set omap4: pandaboard: remove unused hsmmc definition OMAP: McBSP: Remove null omap44xx ops comment OMAP: McBSP: Swap CLKS source definition OMAP: McBSP: Fix CLKR and FSR signal muxing OMAP2+: clock: reduce the amount of standard debugging while disabling unused clocks OMAP: control: move plat-omap/control.h to mach-omap2/control.h OMAP: split plat-omap/common.c OMAP: McBSP: implement functional clock switching via clock framework OMAP: McBSP: implement McBSP CLKR and FSR signal muxing via mach-omap2/mcbsp.c ... Fixed up trivial conflicts in arch/arm/mach-omap2/ {board-zoom-peripherals.c,devices.c} as per Tony
Diffstat (limited to 'arch/arm/mach-omap2/pm34xx.c')
-rw-r--r--arch/arm/mach-omap2/pm34xx.c126
1 files changed, 28 insertions, 98 deletions
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7b03426c72a3..75c0cd13ad8e 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -32,13 +32,11 @@
32#include <plat/sram.h> 32#include <plat/sram.h>
33#include <plat/clockdomain.h> 33#include <plat/clockdomain.h>
34#include <plat/powerdomain.h> 34#include <plat/powerdomain.h>
35#include <plat/control.h>
36#include <plat/serial.h> 35#include <plat/serial.h>
37#include <plat/sdrc.h> 36#include <plat/sdrc.h>
38#include <plat/prcm.h> 37#include <plat/prcm.h>
39#include <plat/gpmc.h> 38#include <plat/gpmc.h>
40#include <plat/dma.h> 39#include <plat/dma.h>
41#include <plat/dmtimer.h>
42 40
43#include <asm/tlbflush.h> 41#include <asm/tlbflush.h>
44 42
@@ -49,16 +47,12 @@
49#include "prm.h" 47#include "prm.h"
50#include "pm.h" 48#include "pm.h"
51#include "sdrc.h" 49#include "sdrc.h"
50#include "control.h"
52 51
53/* Scratchpad offsets */ 52/* Scratchpad offsets */
54#define OMAP343X_TABLE_ADDRESS_OFFSET 0x31 53#define OMAP343X_TABLE_ADDRESS_OFFSET 0xc4
55#define OMAP343X_TABLE_VALUE_OFFSET 0x30 54#define OMAP343X_TABLE_VALUE_OFFSET 0xc0
56#define OMAP343X_CONTROL_REG_VALUE_OFFSET 0x32 55#define OMAP343X_CONTROL_REG_VALUE_OFFSET 0xc8
57
58u32 enable_off_mode;
59u32 sleep_while_idle;
60u32 wakeup_timer_seconds;
61u32 wakeup_timer_milliseconds;
62 56
63struct power_state { 57struct power_state {
64 struct powerdomain *pwrdm; 58 struct powerdomain *pwrdm;
@@ -316,7 +310,7 @@ static void restore_control_register(u32 val)
316/* Function to restore the table entry that was modified for enabling MMU */ 310/* Function to restore the table entry that was modified for enabling MMU */
317static void restore_table_entry(void) 311static void restore_table_entry(void)
318{ 312{
319 u32 *scratchpad_address; 313 void __iomem *scratchpad_address;
320 u32 previous_value, control_reg_value; 314 u32 previous_value, control_reg_value;
321 u32 *address; 315 u32 *address;
322 316
@@ -351,7 +345,6 @@ void omap_sram_idle(void)
351 int core_next_state = PWRDM_POWER_ON; 345 int core_next_state = PWRDM_POWER_ON;
352 int core_prev_state, per_prev_state; 346 int core_prev_state, per_prev_state;
353 u32 sdrc_pwr = 0; 347 u32 sdrc_pwr = 0;
354 int per_state_modified = 0;
355 348
356 if (!_omap_sram_idle) 349 if (!_omap_sram_idle)
357 return; 350 return;
@@ -385,9 +378,9 @@ void omap_sram_idle(void)
385 /* Enable IO-PAD and IO-CHAIN wakeups */ 378 /* Enable IO-PAD and IO-CHAIN wakeups */
386 per_next_state = pwrdm_read_next_pwrst(per_pwrdm); 379 per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
387 core_next_state = pwrdm_read_next_pwrst(core_pwrdm); 380 core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
388 if (omap3_has_io_wakeup() && \ 381 if (omap3_has_io_wakeup() &&
389 (per_next_state < PWRDM_POWER_ON || 382 (per_next_state < PWRDM_POWER_ON ||
390 core_next_state < PWRDM_POWER_ON)) { 383 core_next_state < PWRDM_POWER_ON)) {
391 prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN); 384 prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
392 omap3_enable_io_chain(); 385 omap3_enable_io_chain();
393 } 386 }
@@ -395,20 +388,12 @@ void omap_sram_idle(void)
395 /* PER */ 388 /* PER */
396 if (per_next_state < PWRDM_POWER_ON) { 389 if (per_next_state < PWRDM_POWER_ON) {
397 omap_uart_prepare_idle(2); 390 omap_uart_prepare_idle(2);
391 omap_uart_prepare_idle(3);
398 omap2_gpio_prepare_for_idle(per_next_state); 392 omap2_gpio_prepare_for_idle(per_next_state);
399 if (per_next_state == PWRDM_POWER_OFF) { 393 if (per_next_state == PWRDM_POWER_OFF)
400 if (core_next_state == PWRDM_POWER_ON) {
401 per_next_state = PWRDM_POWER_RET;
402 pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
403 per_state_modified = 1;
404 } else
405 omap3_per_save_context(); 394 omap3_per_save_context();
406 }
407 } 395 }
408 396
409 if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
410 omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);
411
412 /* CORE */ 397 /* CORE */
413 if (core_next_state < PWRDM_POWER_ON) { 398 if (core_next_state < PWRDM_POWER_ON) {
414 omap_uart_prepare_idle(0); 399 omap_uart_prepare_idle(0);
@@ -475,8 +460,7 @@ void omap_sram_idle(void)
475 if (per_prev_state == PWRDM_POWER_OFF) 460 if (per_prev_state == PWRDM_POWER_OFF)
476 omap3_per_restore_context(); 461 omap3_per_restore_context();
477 omap_uart_resume_idle(2); 462 omap_uart_resume_idle(2);
478 if (per_state_modified) 463 omap_uart_resume_idle(3);
479 pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
480 } 464 }
481 465
482 /* Disable IO-PAD and IO-CHAIN wakeup */ 466 /* Disable IO-PAD and IO-CHAIN wakeup */
@@ -501,51 +485,6 @@ int omap3_can_sleep(void)
501 return 1; 485 return 1;
502} 486}
503 487
504/* This sets pwrdm state (other than mpu & core. Currently only ON &
505 * RET are supported. Function is assuming that clkdm doesn't have
506 * hw_sup mode enabled. */
507int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
508{
509 u32 cur_state;
510 int sleep_switch = 0;
511 int ret = 0;
512
513 if (pwrdm == NULL || IS_ERR(pwrdm))
514 return -EINVAL;
515
516 while (!(pwrdm->pwrsts & (1 << state))) {
517 if (state == PWRDM_POWER_OFF)
518 return ret;
519 state--;
520 }
521
522 cur_state = pwrdm_read_next_pwrst(pwrdm);
523 if (cur_state == state)
524 return ret;
525
526 if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
527 omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
528 sleep_switch = 1;
529 pwrdm_wait_transition(pwrdm);
530 }
531
532 ret = pwrdm_set_next_pwrst(pwrdm, state);
533 if (ret) {
534 printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
535 pwrdm->name);
536 goto err;
537 }
538
539 if (sleep_switch) {
540 omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
541 pwrdm_wait_transition(pwrdm);
542 pwrdm_state_switch(pwrdm);
543 }
544
545err:
546 return ret;
547}
548
549static void omap3_pm_idle(void) 488static void omap3_pm_idle(void)
550{ 489{
551 local_irq_disable(); 490 local_irq_disable();
@@ -567,23 +506,6 @@ out:
567#ifdef CONFIG_SUSPEND 506#ifdef CONFIG_SUSPEND
568static suspend_state_t suspend_state; 507static suspend_state_t suspend_state;
569 508
570static void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
571{
572 u32 tick_rate, cycles;
573
574 if (!seconds && !milliseconds)
575 return;
576
577 tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
578 cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
579 omap_dm_timer_stop(gptimer_wakeup);
580 omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
581
582 pr_info("PM: Resume timer in %u.%03u secs"
583 " (%d ticks at %d ticks/sec.)\n",
584 seconds, milliseconds, cycles, tick_rate);
585}
586
587static int omap3_pm_prepare(void) 509static int omap3_pm_prepare(void)
588{ 510{
589 disable_hlt(); 511 disable_hlt();
@@ -604,7 +526,7 @@ static int omap3_pm_suspend(void)
604 pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm); 526 pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
605 /* Set ones wanted by suspend */ 527 /* Set ones wanted by suspend */
606 list_for_each_entry(pwrst, &pwrst_list, node) { 528 list_for_each_entry(pwrst, &pwrst_list, node) {
607 if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state)) 529 if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
608 goto restore; 530 goto restore;
609 if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm)) 531 if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
610 goto restore; 532 goto restore;
@@ -625,7 +547,7 @@ restore:
625 pwrst->pwrdm->name, pwrst->next_state); 547 pwrst->pwrdm->name, pwrst->next_state);
626 ret = -1; 548 ret = -1;
627 } 549 }
628 set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); 550 omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
629 } 551 }
630 if (ret) 552 if (ret)
631 printk(KERN_ERR "Could not enter target state in pm_suspend\n"); 553 printk(KERN_ERR "Could not enter target state in pm_suspend\n");
@@ -756,6 +678,14 @@ static void __init omap3_d2d_idle(void)
756 678
757static void __init prcm_setup_regs(void) 679static void __init prcm_setup_regs(void)
758{ 680{
681 u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ?
682 OMAP3630_AUTO_UART4_MASK : 0;
683 u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
684 OMAP3630_EN_UART4_MASK : 0;
685 u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
686 OMAP3630_GRPSEL_UART4_MASK : 0;
687
688
759 /* XXX Reset all wkdeps. This should be done when initializing 689 /* XXX Reset all wkdeps. This should be done when initializing
760 * powerdomains */ 690 * powerdomains */
761 prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP); 691 prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
@@ -842,6 +772,7 @@ static void __init prcm_setup_regs(void)
842 CM_AUTOIDLE); 772 CM_AUTOIDLE);
843 773
844 cm_write_mod_reg( 774 cm_write_mod_reg(
775 omap3630_auto_uart4_mask |
845 OMAP3430_AUTO_GPIO6_MASK | 776 OMAP3430_AUTO_GPIO6_MASK |
846 OMAP3430_AUTO_GPIO5_MASK | 777 OMAP3430_AUTO_GPIO5_MASK |
847 OMAP3430_AUTO_GPIO4_MASK | 778 OMAP3430_AUTO_GPIO4_MASK |
@@ -918,14 +849,16 @@ static void __init prcm_setup_regs(void)
918 OMAP3430_DSS_MOD, PM_WKEN); 849 OMAP3430_DSS_MOD, PM_WKEN);
919 850
920 /* Enable wakeups in PER */ 851 /* Enable wakeups in PER */
921 prm_write_mod_reg(OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK | 852 prm_write_mod_reg(omap3630_en_uart4_mask |
853 OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
922 OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK | 854 OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
923 OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK | 855 OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
924 OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK | 856 OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK |
925 OMAP3430_EN_MCBSP4_MASK, 857 OMAP3430_EN_MCBSP4_MASK,
926 OMAP3430_PER_MOD, PM_WKEN); 858 OMAP3430_PER_MOD, PM_WKEN);
927 /* and allow them to wake up MPU */ 859 /* and allow them to wake up MPU */
928 prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2_MASK | 860 prm_write_mod_reg(omap3630_grpsel_uart4_mask |
861 OMAP3430_GRPSEL_GPIO2_MASK |
929 OMAP3430_GRPSEL_GPIO3_MASK | 862 OMAP3430_GRPSEL_GPIO3_MASK |
930 OMAP3430_GRPSEL_GPIO4_MASK | 863 OMAP3430_GRPSEL_GPIO4_MASK |
931 OMAP3430_GRPSEL_GPIO5_MASK | 864 OMAP3430_GRPSEL_GPIO5_MASK |
@@ -974,7 +907,7 @@ void omap3_pm_off_mode_enable(int enable)
974 907
975 list_for_each_entry(pwrst, &pwrst_list, node) { 908 list_for_each_entry(pwrst, &pwrst_list, node) {
976 pwrst->next_state = state; 909 pwrst->next_state = state;
977 set_pwrdm_state(pwrst->pwrdm, state); 910 omap_set_pwrdm_state(pwrst->pwrdm, state);
978 } 911 }
979} 912}
980 913
@@ -1019,7 +952,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
1019 if (pwrdm_has_hdwr_sar(pwrdm)) 952 if (pwrdm_has_hdwr_sar(pwrdm))
1020 pwrdm_enable_hdwr_sar(pwrdm); 953 pwrdm_enable_hdwr_sar(pwrdm);
1021 954
1022 return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); 955 return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
1023} 956}
1024 957
1025/* 958/*
@@ -1029,9 +962,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
1029 */ 962 */
1030static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) 963static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
1031{ 964{
1032 clkdm_clear_all_wkdeps(clkdm);
1033 clkdm_clear_all_sleepdeps(clkdm);
1034
1035 if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) 965 if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
1036 omap2_clkdm_allow_idle(clkdm); 966 omap2_clkdm_allow_idle(clkdm);
1037 else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && 967 else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&