264 lines
8.5 KiB
Diff
264 lines
8.5 KiB
Diff
|
From 358429b39b6801f4856e7c80d2c58ac7be4bd0bc Mon Sep 17 00:00:00 2001
|
||
|
From: Andy Green <andy@openmoko.com>
|
||
|
Date: Wed, 2 Jul 2008 22:41:14 +0100
|
||
|
Subject: [PATCH] fix-pcf50633-kill-white-splash-of-death-on-suspend.patch
|
||
|
|
||
|
mach-gta02 meddles with the regulator platform struct after
|
||
|
it is defined, leading to LCM power getting lost in suspend
|
||
|
despite I set it to be left up. Fixing this finally removes
|
||
|
the incredibly stubborn white LCM on suspend "flash".
|
||
|
|
||
|
This is also going to be implicated in Sean McNeil's
|
||
|
experience of monochromatic LCM after resume, which was
|
||
|
previously attacked by resetting and re-initing the LCM
|
||
|
from scratch.
|
||
|
|
||
|
In addition, I realized that we take down core_1v3 in
|
||
|
pcf50633 suspend action, this is happening near the
|
||
|
start of suspend, so we are in a meta-race to finish
|
||
|
suspend in a controlled way before the caps on core_1v3
|
||
|
run out (I only saw 23.3uF total). If it's true, this
|
||
|
is where the weirdo sensitivity to timing during
|
||
|
suspend is coming from.
|
||
|
|
||
|
Therefore in this patch we also remove sleeps and
|
||
|
dev_info() etc (which have to flush on serial console)
|
||
|
from the pc50633 isr workqueue if we are in pcf50633
|
||
|
driver suspend state 1, ie, suspending... because we
|
||
|
don't have time for it.
|
||
|
|
||
|
Signed-off-by: Andy Green <andy@openmoko.com>
|
||
|
---
|
||
|
arch/arm/mach-s3c2440/mach-gta02.c | 43 ++++++++++++++++++++++++++----------
|
||
|
drivers/i2c/chips/pcf50633.c | 29 ++++++++++++-----------
|
||
|
drivers/mfd/glamo/glamo-core.c | 2 +
|
||
|
drivers/video/display/jbt6k74.c | 1 +
|
||
|
4 files changed, 49 insertions(+), 26 deletions(-)
|
||
|
|
||
|
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
|
||
|
index 654dc8f..0bacafa 100644
|
||
|
--- a/arch/arm/mach-s3c2440/mach-gta02.c
|
||
|
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
|
||
|
@@ -485,6 +485,9 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
|
||
|
[1] = PCF50633_INT2_ONKEYF,
|
||
|
[2] = PCF50633_INT3_ONKEY1S
|
||
|
},
|
||
|
+ /* warning: these get rewritten during machine init below
|
||
|
+ * depending on pcb variant
|
||
|
+ */
|
||
|
.rails = {
|
||
|
[PCF50633_REGULATOR_AUTO] = {
|
||
|
.name = "io_3v3",
|
||
|
@@ -496,6 +499,12 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
|
||
|
},
|
||
|
[PCF50633_REGULATOR_DOWN1] = {
|
||
|
.name = "core_1v3",
|
||
|
+ /* Wow, when we are going into suspend, after pcf50633
|
||
|
+ * runs its suspend (which happens real early since it
|
||
|
+ * is an i2c device) we are running out of the 22uF cap
|
||
|
+ * on core_1v3 rail !!!!
|
||
|
+ */
|
||
|
+ .flags = PMU_VRAIL_F_SUSPEND_ON,
|
||
|
.voltage = {
|
||
|
.init = 1300,
|
||
|
.max = 1600,
|
||
|
@@ -503,6 +512,7 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
|
||
|
},
|
||
|
[PCF50633_REGULATOR_DOWN2] = {
|
||
|
.name = "core_1v8",
|
||
|
+ .flags = PMU_VRAIL_F_SUSPEND_ON,
|
||
|
.voltage = {
|
||
|
.init = 1800,
|
||
|
.max = 1800,
|
||
|
@@ -516,8 +526,7 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
|
||
|
},
|
||
|
},
|
||
|
[PCF50633_REGULATOR_LDO1] = {
|
||
|
- .name = "stby_1v3",
|
||
|
- .flags = PMU_VRAIL_F_SUSPEND_ON,
|
||
|
+ .name = "gsensor_3v3",
|
||
|
.voltage = {
|
||
|
.init = 1300,
|
||
|
.max = 1330,
|
||
|
@@ -531,7 +540,7 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
|
||
|
},
|
||
|
},
|
||
|
[PCF50633_REGULATOR_LDO3] = {
|
||
|
- .name = "lcm_3v",
|
||
|
+ .name = "unused3",
|
||
|
.voltage = {
|
||
|
.init = 3000,
|
||
|
.max = 3000,
|
||
|
@@ -545,20 +554,28 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
|
||
|
},
|
||
|
},
|
||
|
[PCF50633_REGULATOR_LDO5] = {
|
||
|
- .name = "gl_1v5",
|
||
|
+ .name = "rf3v",
|
||
|
.voltage = {
|
||
|
.init = 1500,
|
||
|
.max = 1500,
|
||
|
},
|
||
|
},
|
||
|
[PCF50633_REGULATOR_LDO6] = {
|
||
|
- .name = "user1",
|
||
|
+ .name = "lcm_3v",
|
||
|
.flags = PMU_VRAIL_F_SUSPEND_ON,
|
||
|
.voltage = {
|
||
|
.init = 0,
|
||
|
.max = 3300,
|
||
|
},
|
||
|
},
|
||
|
+ [PCF50633_REGULATOR_MEMLDO] = {
|
||
|
+ .name = "memldo",
|
||
|
+ .flags = PMU_VRAIL_F_SUSPEND_ON,
|
||
|
+ .voltage = {
|
||
|
+ .init = 1800,
|
||
|
+ .max = 1800,
|
||
|
+ },
|
||
|
+ },
|
||
|
},
|
||
|
.defer_resume_backlight = 1,
|
||
|
};
|
||
|
@@ -611,13 +628,15 @@ static void mangle_pmu_pdata_by_system_rev(void)
|
||
|
.max = 3000,
|
||
|
}
|
||
|
});
|
||
|
- gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO6] = ((struct pmu_voltage_rail) {
|
||
|
- .name = "lcm_3v",
|
||
|
- .voltage = {
|
||
|
- .init = 3000,
|
||
|
- .max = 3000,
|
||
|
- }
|
||
|
- });
|
||
|
+ gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO6] =
|
||
|
+ ((struct pmu_voltage_rail) {
|
||
|
+ .name = "lcm_3v",
|
||
|
+ .flags = PMU_VRAIL_F_SUSPEND_ON,
|
||
|
+ .voltage = {
|
||
|
+ .init = 3000,
|
||
|
+ .max = 3000,
|
||
|
+ }
|
||
|
+ });
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
|
||
|
index 2f144bc..2e5981d 100644
|
||
|
--- a/drivers/i2c/chips/pcf50633.c
|
||
|
+++ b/drivers/i2c/chips/pcf50633.c
|
||
|
@@ -750,9 +750,6 @@ static void pcf50633_work(struct work_struct *work)
|
||
|
mutex_lock(&pcf->working_lock);
|
||
|
pcf->working = 1;
|
||
|
|
||
|
- dev_info(&pcf->client.dev, "pcf50633_work called with suspended = %d\n",
|
||
|
- pcf->have_been_suspended);
|
||
|
-
|
||
|
/*
|
||
|
* If we are inside suspend -> resume completion time we don't attempt
|
||
|
* service until we have fully resumed. Although we could talk to the
|
||
|
@@ -763,11 +760,8 @@ static void pcf50633_work(struct work_struct *work)
|
||
|
* completed.
|
||
|
*/
|
||
|
|
||
|
- if (pcf->have_been_suspended && (pcf->have_been_suspended < 3)) {
|
||
|
- dev_info(&pcf->client.dev, "rescheduling, suspended = %d\n",
|
||
|
- pcf->have_been_suspended);
|
||
|
+ if (pcf->have_been_suspended && (pcf->have_been_suspended < 3))
|
||
|
goto reschedule;
|
||
|
- }
|
||
|
|
||
|
/*
|
||
|
* datasheet says we have to read the five IRQ
|
||
|
@@ -1158,9 +1152,13 @@ static void pcf50633_work(struct work_struct *work)
|
||
|
|
||
|
reschedule:
|
||
|
/* don't spew, delaying whatever else is happening */
|
||
|
- msleep(100);
|
||
|
-
|
||
|
- dev_info(&pcf->client.dev, "rescheduling interrupt service\n");
|
||
|
+ /* EXCEPTION: if we are in the middle of suspending, we don't have
|
||
|
+ * time to hang around since we may be turned off core 1V3 already
|
||
|
+ */
|
||
|
+ if (pcf->have_been_suspended != 1) {
|
||
|
+ msleep(50);
|
||
|
+ dev_info(&pcf->client.dev, "rescheduling interrupt service\n");
|
||
|
+ }
|
||
|
if (!schedule_work(&pcf->work))
|
||
|
dev_err(&pcf->client.dev, "int service reschedule failed\n");
|
||
|
|
||
|
@@ -2340,7 +2338,7 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
|
||
|
PCF50633_REG_AUTOOUT,
|
||
|
sizeof(pcf->standby_regs.misc),
|
||
|
&pcf->standby_regs.misc[0]);
|
||
|
- if (ret != 18)
|
||
|
+ if (ret != sizeof(pcf->standby_regs.misc))
|
||
|
dev_err(dev, "Failed to save misc levels and enables :-(\n");
|
||
|
|
||
|
/* regulator voltages and enable states */
|
||
|
@@ -2348,7 +2346,7 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
|
||
|
PCF50633_REG_LDO1OUT,
|
||
|
sizeof(pcf->standby_regs.ldo),
|
||
|
&pcf->standby_regs.ldo[0]);
|
||
|
- if (ret != 14)
|
||
|
+ if (ret != sizeof(pcf->standby_regs.ldo))
|
||
|
dev_err(dev, "Failed to save LDO levels and enables :-(\n");
|
||
|
|
||
|
/* switch off power supplies that are not needed during suspend */
|
||
|
@@ -2356,8 +2354,6 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
|
||
|
if ((pcf->pdata->rails[i].flags & PMU_VRAIL_F_SUSPEND_ON))
|
||
|
continue;
|
||
|
|
||
|
- dev_dbg(dev, "disabling regulator %u\n", i);
|
||
|
-
|
||
|
/* we can save ourselves the read part of a read-modify-write
|
||
|
* here because we captured all these already
|
||
|
*/
|
||
|
@@ -2366,6 +2362,11 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
|
||
|
else
|
||
|
tmp = pcf->standby_regs.ldo[(i - 4) * 2 + 1];
|
||
|
|
||
|
+ dev_info(dev, "disabling reg %s by setting ENA %d to 0x%02X\n",
|
||
|
+ pcf->pdata->rails[i].name,
|
||
|
+ regulator_registers[i] + 1, tmp & 0xfe);
|
||
|
+
|
||
|
+ /* associated enable is always +1 from OUT reg */
|
||
|
__reg_write(pcf, regulator_registers[i] + 1, tmp & 0xfe);
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
|
||
|
index 2a02f9c..2412b7d 100644
|
||
|
--- a/drivers/mfd/glamo/glamo-core.c
|
||
|
+++ b/drivers/mfd/glamo/glamo-core.c
|
||
|
@@ -848,6 +848,7 @@ static void glamo_power(struct glamo_core *glamo,
|
||
|
ARRAY_SIZE(glamo_resume_script), 0);
|
||
|
|
||
|
break;
|
||
|
+
|
||
|
case GLAMO_POWER_STANDBY:
|
||
|
/* enable memory self-refresh */
|
||
|
__reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM1,
|
||
|
@@ -859,6 +860,7 @@ static void glamo_power(struct glamo_core *glamo,
|
||
|
__reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0xffff);
|
||
|
__reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x0001, 0xffff);
|
||
|
break;
|
||
|
+
|
||
|
case GLAMO_POWER_SUSPEND:
|
||
|
__reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2,
|
||
|
GLAMO_MEM_DRAM2_DEEP_PWRDOWN, 0xffff);
|
||
|
diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
|
||
|
index 6fa1fe7..b406298 100644
|
||
|
--- a/drivers/video/display/jbt6k74.c
|
||
|
+++ b/drivers/video/display/jbt6k74.c
|
||
|
@@ -634,6 +634,7 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state)
|
||
|
|
||
|
/* Save mode for resume */
|
||
|
jbt->last_state = jbt->state;
|
||
|
+
|
||
|
jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
|
||
|
|
||
|
jbt->have_resumed = 0;
|
||
|
--
|
||
|
1.5.6.5
|
||
|
|