GPIO driver strength settings are not preserved across suspend/resume
for s5pc100, s5pv210 and Exynos platforms which has been the cause of
mmc/sd card read/write failures after resume. Fix this by saving and
restoring the GPIO driver strength register settings across suspend/resume.

Signed-off-by: Inderpal Singh <inderpal.si...@linaro.org>
---
1. This change is applicable only for s5pc100, s5pv210 and Exynos
platforms. For all other platforms, the driver strength registers are
part of special port configuration register (SPCON) and these
registers are saved and restored separately from the GPIO bank
registers. For s5pc100, s5pv210 and Exynos platforms, the driver
strength values are saved along with the GPIO bank registers.

2. An additional entry is added to the 'pm_save' array of 'struct
samsung_gpio_chip' for saving driver strength values.

3. Tested with v210 and v310 smdk boards

 arch/arm/plat-samsung/include/plat/gpio-core.h |    2 +-
 arch/arm/plat-samsung/pm-gpio.c                |   13 +++++++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h 
b/arch/arm/plat-samsung/include/plat/gpio-core.h
index 1fe6917..8871b4c 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -69,7 +69,7 @@ struct samsung_gpio_chip {
        int                     group;
        spinlock_t               lock;
 #ifdef CONFIG_PM
-       u32                     pm_save[4];
+       u32                     pm_save[5];
 #endif
 };
 
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
index 4be016e..5493f38 100644
--- a/arch/arm/plat-samsung/pm-gpio.c
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -21,12 +21,14 @@
 
 #include <plat/gpio-core.h>
 #include <plat/pm.h>
+#include <plat/cpu.h>
 
 /* PM GPIO helpers */
 
 #define OFFS_CON       (0x00)
 #define OFFS_DAT       (0x04)
 #define OFFS_UP                (0x08)
+#define OFFS_DRV_STRGTH        (0x0C)
 
 static void samsung_gpio_pm_1bit_save(struct samsung_gpio_chip *chip)
 {
@@ -199,6 +201,9 @@ static void samsung_gpio_pm_4bit_save(struct 
samsung_gpio_chip *chip)
        chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
        chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
 
+       if (soc_is_s5pc100() || soc_is_s5pv210() || soc_is_exynos4210())
+               chip->pm_save[4] = __raw_readl(chip->base + OFFS_DRV_STRGTH);
+
        if (chip->chip.ngpio > 8)
                chip->pm_save[0] = __raw_readl(chip->base - 4);
 }
@@ -285,6 +290,9 @@ static void samsung_gpio_pm_4bit_resume(struct 
samsung_gpio_chip *chip)
        __raw_writel(chip->pm_save[2], base + OFFS_DAT);
        __raw_writel(chip->pm_save[3], base + OFFS_UP);
 
+       if (soc_is_s5pc100() || soc_is_s5pv210() || soc_is_exynos4210())
+               __raw_writel(chip->pm_save[4], base + OFFS_DRV_STRGTH);
+
        if (chip->chip.ngpio > 8) {
                S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
                          chip->chip.label, old_gpcon[0], old_gpcon[1],
@@ -338,12 +346,13 @@ void samsung_pm_save_gpios(void)
 
                samsung_pm_save_gpio(ourchip);
 
-               S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
+               S3C_PMDBG("%s: save %08x,%08x,%08x,%08x,%08x\n",
                          ourchip->chip.label,
                          ourchip->pm_save[0],
                          ourchip->pm_save[1],
                          ourchip->pm_save[2],
-                         ourchip->pm_save[3]);
+                         ourchip->pm_save[3],
+                         ourchip->pm_save[4]);
 
                gpio_nr += ourchip->chip.ngpio;
                gpio_nr += CONFIG_S3C_GPIO_SPACE;
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to