diff options
author | Paul Walmsley <paul@pwsan.com> | 2011-10-06 19:18:45 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@ti.com> | 2011-10-07 16:41:49 -0400 |
commit | b02b917211d50ad5dc13e49c933ef916b10e0d00 (patch) | |
tree | 138707c1aab31b0263cb1bd02ba4678c6a7d80f5 /arch/arm/mach-omap2/pm34xx.c | |
parent | ff2f8e5ffb23de6e2284f31651447cb80a4c9d1b (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.c | 43 |
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 | ||
122 | static void omap3_disable_io_chain(void) | 119 | static 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 | ||
129 | static void omap3_core_save_context(void) | 125 | static 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 |