aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy@openmoko.com>2008-11-19 17:09:47 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-11-19 17:09:47 +0000
commit11c78492dc87877aaf1220b6b855e4a9363ca932 (patch)
tree5ea1eae6f5e568ac339a712a55b29b743b837ab7
parentf8d84454949a5669abccf0b9c524f46380050c7f (diff)
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>
-rw-r--r--arch/arm/mach-s3c2440/mach-gta02.c17
-rw-r--r--drivers/i2c/chips/pcf50633.c14
-rw-r--r--include/linux/pcf50633.h5
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 22de1819475..5980ea9110e 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 c148ea7191e..82ee2f0bf16 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 8a75b28606f..0522d922fcc 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