aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/pm34xx.c
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2011-10-06 19:18:45 -0400
committerKevin Hilman <khilman@ti.com>2011-10-07 16:41:49 -0400
commitb02b917211d50ad5dc13e49c933ef916b10e0d00 (patch)
tree138707c1aab31b0263cb1bd02ba4678c6a7d80f5 /arch/arm/mach-omap2/pm34xx.c
parentff2f8e5ffb23de6e2284f31651447cb80a4c9d1b (diff)
ARM: OMAP3: PM: fix I/O wakeup and I/O chain clock control detection
The way that we detect which OMAP3 chips support I/O wakeup and software I/O chain clock control is broken. Currently, I/O wakeup is marked as present for all OMAP3 SoCs other than the AM3505/3517. The TI81xx family of SoCs are at present considered to be OMAP3 SoCs, but don't support I/O wakeup. To resolve this, convert the existing blacklist approach to an explicit, whitelist support, in which only SoCs which are known to support I/O wakeup are listed. (At present, this only includes OMAP34xx, OMAP3503, OMAP3515, OMAP3525, OMAP3530, and OMAP36xx.) Also, the current code incorrectly detects the presence of a software-controllable I/O chain clock on several chips that don't support it. This results in writes to reserved bitfields, unnecessary delays, and console messages on kernels running on those chips: http://www.spinics.net/lists/linux-omap/msg58735.html Convert this test to a feature test with a chip-by-chip whitelist. Thanks to Dave Hylands <dhylands@gmail.com> for reporting this problem and doing some testing to help isolate the cause. Thanks to Steve Sakoman <sakoman@gmail.com> for catching a bug in the first version of this patch. Thanks to Russell King <linux@arm.linux.org.uk> for comments. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Dave Hylands <dhylands@gmail.com> Cc: Steve Sakoman <sakoman@gmail.com> Tested-by: Steve Sakoman <sakoman@gmail.com> Cc: Russell King - ARM Linux <linux@arm.linux.org.uk> Signed-off-by: Kevin Hilman <khilman@ti.com>
Diffstat (limited to 'arch/arm/mach-omap2/pm34xx.c')
-rw-r--r--arch/arm/mach-omap2/pm34xx.c43
1 files changed, 22 insertions, 21 deletions
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 1915050e9401..bfa8b8c8171a 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -99,31 +99,27 @@ static void omap3_enable_io_chain(void)
99{ 99{
100 int timeout = 0; 100 int timeout = 0;
101 101
102 if (omap_rev() >= OMAP3430_REV_ES3_1) { 102 omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
103 omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, 103 PM_WKEN);
104 PM_WKEN); 104 /* Do a readback to assure write has been done */
105 /* Do a readback to assure write has been done */ 105 omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
106 omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN); 106
107 107 while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
108 while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) & 108 OMAP3430_ST_IO_CHAIN_MASK)) {
109 OMAP3430_ST_IO_CHAIN_MASK)) { 109 timeout++;
110 timeout++; 110 if (timeout > 1000) {
111 if (timeout > 1000) { 111 pr_err("Wake up daisy chain activation failed.\n");
112 printk(KERN_ERR "Wake up daisy chain " 112 return;
113 "activation failed.\n");
114 return;
115 }
116 omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
117 WKUP_MOD, PM_WKEN);
118 } 113 }
114 omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
115 WKUP_MOD, PM_WKEN);
119 } 116 }
120} 117}
121 118
122static void omap3_disable_io_chain(void) 119static void omap3_disable_io_chain(void)
123{ 120{
124 if (omap_rev() >= OMAP3430_REV_ES3_1) 121 omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
125 omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, 122 PM_WKEN);
126 PM_WKEN);
127} 123}
128 124
129static void omap3_core_save_context(void) 125static void omap3_core_save_context(void)
@@ -375,7 +371,8 @@ void omap_sram_idle(void)
375 (per_next_state < PWRDM_POWER_ON || 371 (per_next_state < PWRDM_POWER_ON ||
376 core_next_state < PWRDM_POWER_ON)) { 372 core_next_state < PWRDM_POWER_ON)) {
377 omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN); 373 omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
378 omap3_enable_io_chain(); 374 if (omap3_has_io_chain_ctrl())
375 omap3_enable_io_chain();
379 } 376 }
380 377
381 /* Block console output in case it is on one of the OMAP UARTs */ 378 /* Block console output in case it is on one of the OMAP UARTs */
@@ -478,7 +475,8 @@ console_still_active:
478 core_next_state < PWRDM_POWER_ON)) { 475 core_next_state < PWRDM_POWER_ON)) {
479 omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, 476 omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
480 PM_WKEN); 477 PM_WKEN);
481 omap3_disable_io_chain(); 478 if (omap3_has_io_chain_ctrl())
479 omap3_disable_io_chain();
482 } 480 }
483 481
484 clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); 482 clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
@@ -871,6 +869,9 @@ static int __init omap3_pm_init(void)
871 if (!cpu_is_omap34xx()) 869 if (!cpu_is_omap34xx())
872 return -ENODEV; 870 return -ENODEV;
873 871
872 if (!omap3_has_io_chain_ctrl())
873 pr_warning("PM: no software I/O chain control; some wakeups may be lost\n");
874
874 pm_errata_configure(); 875 pm_errata_configure();
875 876
876 /* XXX prcm_setup_regs needs to be before enabling hw 877 /* XXX prcm_setup_regs needs to be before enabling hw