diff options
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.26/1160-fix-glamo-mci-relationship-with-pcf50633-suspend-res.patch')
-rwxr-xr-x | target/linux/s3c24xx/patches-2.6.26/1160-fix-glamo-mci-relationship-with-pcf50633-suspend-res.patch | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.26/1160-fix-glamo-mci-relationship-with-pcf50633-suspend-res.patch b/target/linux/s3c24xx/patches-2.6.26/1160-fix-glamo-mci-relationship-with-pcf50633-suspend-res.patch new file mode 100755 index 0000000..9183193 --- /dev/null +++ b/target/linux/s3c24xx/patches-2.6.26/1160-fix-glamo-mci-relationship-with-pcf50633-suspend-res.patch @@ -0,0 +1,110 @@ +From 7af35792e1165cb9258e192ddfcb03393eb76f86 Mon Sep 17 00:00:00 2001 +From: Andy Green <andy@openmoko.com> +Date: Fri, 25 Jul 2008 23:06:12 +0100 +Subject: [PATCH] fix-glamo-mci-relationship-with-pcf50633-suspend-resume.patch + +After protecting pcf50633 read and write primitives against +operation after suspend or before resume (by blowing a +stack_trace()) I saw glamo-mci was trying to use pcf50633 +at these bad times on its own suspend and resume. Since that +part was already done via platform callback, I added an +export in pcf50633 that tells you if it is ready or busy, +and used it to defer (resume power on case) or ignore +(suspend power off case, since pcf50633 already did it) +the mci power call. + +Signed-off-by: Andy Green <andy@openmoko.com> +--- + arch/arm/mach-s3c2440/mach-gta02.c | 17 ++++++++++------- + drivers/i2c/chips/pcf50633.c | 14 ++++++++++++++ + include/linux/pcf50633.h | 5 +++++ + 3 files changed, 29 insertions(+), 7 deletions(-) + +diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c +index 22de181..5980ea9 100644 +--- a/arch/arm/mach-s3c2440/mach-gta02.c ++++ b/arch/arm/mach-s3c2440/mach-gta02.c +@@ -1277,13 +1277,12 @@ gta02_glamo_mmc_set_power(unsigned char power_mode, unsigned short vdd) + case GTA02v4_SYSTEM_REV: + case GTA02v5_SYSTEM_REV: + case GTA02v6_SYSTEM_REV: +- /* depend on pcf50633 driver init */ +- if (!pcf50633_global) +- while (!pcf50633_global) +- msleep(10); + switch (power_mode) { + case MMC_POWER_ON: + case MMC_POWER_UP: ++ /* depend on pcf50633 driver init + not suspended */ ++ while (pcf50633_ready(pcf50633_global)) ++ msleep(1); + /* select and set the voltage */ + if (vdd > 7) { + mv += 300 + 100 * (vdd - 8); +@@ -1292,15 +1291,19 @@ gta02_glamo_mmc_set_power(unsigned char power_mode, unsigned short vdd) + } + pcf50633_voltage_set(pcf50633_global, + PCF50633_REGULATOR_HCLDO, mv); +- msleep(10); + pcf50633_onoff_set(pcf50633_global, + PCF50633_REGULATOR_HCLDO, 1); +- msleep(1); + break; + case MMC_POWER_OFF: ++ /* power off happens during suspend, when pcf50633 can ++ * be already gone and not coming back... just forget ++ * the action then because pcf50633 suspend already ++ * dealt with it, otherwise we spin forever ++ */ ++ if (pcf50633_ready(pcf50633_global)) ++ return; + pcf50633_onoff_set(pcf50633_global, + PCF50633_REGULATOR_HCLDO, 0); +- msleep(1); + break; + } + break; +diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c +index c148ea7..82ee2f0 100644 +--- a/drivers/i2c/chips/pcf50633.c ++++ b/drivers/i2c/chips/pcf50633.c +@@ -2230,6 +2230,20 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state) + return 0; + } + ++ ++int pcf50633_ready(struct pcf50633_data *pcf) ++{ ++ if (!pcf) ++ return -EBUSY; ++ ++ if (pcf->have_been_suspended) ++ return -EBUSY; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(pcf50633_ready); ++ ++ + /* + * if backlight resume is selected to be deferred by platform, then it + * can call this to finally reset backlight status (after LCM is resumed +diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h +index 8a75b28..0522d92 100644 +--- a/include/linux/pcf50633.h ++++ b/include/linux/pcf50633.h +@@ -129,6 +129,11 @@ extern void + pcf50633_register_resume_dependency(struct pcf50633_data *pcf, + struct resume_dependency *dep); + ++/* 0 = initialized and resumed and ready to roll, !=0 = either not ++ * initialized or not resumed yet ++ */ ++extern int ++pcf50633_ready(struct pcf50633_data *pcf); + + #define PCF50633_FEAT_EXTON 0x00000001 /* not yet supported */ + #define PCF50633_FEAT_MBC 0x00000002 +-- +1.5.6.3 + |