diff options
author | Igor Grinberg <grinberg@compulab.co.il> | 2012-04-12 08:43:28 -0400 |
---|---|---|
committer | Haojian Zhuang <haojian.zhuang@gmail.com> | 2012-04-26 23:11:50 -0400 |
commit | a13b878780ea98d8415203c4502a8fc5bc614656 (patch) | |
tree | 2ffed2d5b92cca357fec94a15d3427783693a9ab /arch | |
parent | 9f9d27e3f3317f39c91c286b6184f1ca05452968 (diff) |
ARM: PXA2xx: MFP: fix bug with MFP_LPM_KEEP_OUTPUT
Pins that have MFP_LPM_KEEP_OUTPUT set and are configured for output
must retain the output state in low power mode.
Currently, the pin direction configuration is overrided with values
in gpdr_lpm[] array and do not obey the MFP_LPM_KEEP_OUTPUT setting.
Fix the above bug and add some documentation to clarify the
MFP_LPM_KEEP_OUTPUT setting purpose.
Reported-by: Paul Parsons <lost.distance@yahoo.com>
Signed-off-by: Igor Grinberg <grinberg@compulab.co.il>
Tested-by: Paul Parsons <lost.distance@yahoo.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-pxa/mfp-pxa2xx.c | 12 |
2 files changed, 17 insertions, 2 deletions
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h index c54cef25895c..cbf51ae81855 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | |||
@@ -17,6 +17,7 @@ | |||
17 | * | 17 | * |
18 | * bit 23 - Input/Output (PXA2xx specific) | 18 | * bit 23 - Input/Output (PXA2xx specific) |
19 | * bit 24 - Wakeup Enable(PXA2xx specific) | 19 | * bit 24 - Wakeup Enable(PXA2xx specific) |
20 | * bit 25 - Keep Output (PXA2xx specific) | ||
20 | */ | 21 | */ |
21 | 22 | ||
22 | #define MFP_DIR_IN (0x0 << 23) | 23 | #define MFP_DIR_IN (0x0 << 23) |
@@ -25,6 +26,12 @@ | |||
25 | #define MFP_DIR(x) (((x) >> 23) & 0x1) | 26 | #define MFP_DIR(x) (((x) >> 23) & 0x1) |
26 | 27 | ||
27 | #define MFP_LPM_CAN_WAKEUP (0x1 << 24) | 28 | #define MFP_LPM_CAN_WAKEUP (0x1 << 24) |
29 | |||
30 | /* | ||
31 | * MFP_LPM_KEEP_OUTPUT must be specified for pins that need to | ||
32 | * retain their last output level (low or high). | ||
33 | * Note: MFP_LPM_KEEP_OUTPUT has no effect on pins configured for input. | ||
34 | */ | ||
28 | #define MFP_LPM_KEEP_OUTPUT (0x1 << 25) | 35 | #define MFP_LPM_KEEP_OUTPUT (0x1 << 25) |
29 | 36 | ||
30 | #define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE) | 37 | #define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE) |
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index b0a842887780..d2373d79b657 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c | |||
@@ -366,14 +366,22 @@ static int pxa2xx_mfp_suspend(void) | |||
366 | } | 366 | } |
367 | 367 | ||
368 | for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { | 368 | for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { |
369 | |||
370 | saved_gafr[0][i] = GAFR_L(i); | 369 | saved_gafr[0][i] = GAFR_L(i); |
371 | saved_gafr[1][i] = GAFR_U(i); | 370 | saved_gafr[1][i] = GAFR_U(i); |
372 | saved_gpdr[i] = GPDR(i * 32); | 371 | saved_gpdr[i] = GPDR(i * 32); |
373 | saved_pgsr[i] = PGSR(i); | 372 | saved_pgsr[i] = PGSR(i); |
373 | } | ||
374 | 374 | ||
375 | GPDR(i * 32) = gpdr_lpm[i]; | 375 | /* set GPDR bits taking into account MFP_LPM_KEEP_OUTPUT */ |
376 | for (i = 0; i < pxa_last_gpio; i++) { | ||
377 | if ((gpdr_lpm[gpio_to_bank(i)] & GPIO_bit(i)) || | ||
378 | ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) && | ||
379 | (saved_gpdr[gpio_to_bank(i)] & GPIO_bit(i)))) | ||
380 | GPDR(i) |= GPIO_bit(i); | ||
381 | else | ||
382 | GPDR(i) &= ~GPIO_bit(i); | ||
376 | } | 383 | } |
384 | |||
377 | return 0; | 385 | return 0; |
378 | } | 386 | } |
379 | 387 | ||