[PATCH 4/5] add-use-pcf50633-resume-callback-jbt6k74.patch

Andy Green andy at openmoko.com
Mon Jun 2 14:27:58 CEST 2008


Adds the resume callback stuff to glamo, then changes
jbt6k74 to no longer use a sleeping workqueue, but to
make its resume actions dependent on pcf50633 and
glamo resume (for backlight and communication to LCM
respectively)

Signed-off-by: Andy Green <andy at openmoko.com>
---

 arch/arm/mach-s3c2440/mach-gta02.c |   39 ++++++++++++++++++++-
 drivers/i2c/chips/pcf50633.c       |   17 +++------
 drivers/mfd/glamo/glamo-core.c     |   16 +++++++++
 drivers/mfd/glamo/glamo-core.h     |    3 +-
 drivers/video/display/jbt6k74.c    |   67 +++++++++++++++++++-----------------
 include/linux/glamofb.h            |    3 ++
 include/linux/jbt6k74.h            |    4 ++
 include/linux/pcf50633.h           |    2 +
 include/linux/resume-dependency.h  |   10 +++--
 9 files changed, 108 insertions(+), 53 deletions(-)

diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index c1ab1ae..983dc8d 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -91,6 +91,12 @@ extern struct neospy_logdata neospy;
 /* arbitrates which sensor IRQ owns the shared SPI bus */
 static spinlock_t motion_irq_lock;
 
+/* the dependency of jbt / LCM on pcf50633 resume */
+struct resume_dependency resume_dep_jbt_pcf;
+/* the dependency of jbt / LCM on glamo resume */
+struct resume_dependency resume_dep_jbt_glamo;
+
+
 /* define FIQ IPC struct */
 /*
  * contains stuff FIQ ISR modifies and normal kernel code can see and use
@@ -860,21 +866,50 @@ static struct s3c2410_ts_mach_info gta02_ts_cfg = {
 
 /* SPI: LCM control interface attached to Glamo3362 */
 
-void gta02_jbt6k74_reset(int devidx, int level)
+static void gta02_jbt6k74_reset(int devidx, int level)
 {
 	glamo_lcm_reset(level);
 }
 
 /* finally bring up deferred backlight resume now LCM is resumed itself */
 
-void gta02_jbt6k74_resuming(int devidx)
+static void gta02_jbt6k74_resuming(int devidx)
 {
 	pcf50633_backlight_resume(pcf50633_global);
 }
 
+static int gta02_jbt6k74_all_dependencies_resumed(int devidx)
+{
+	if (!resume_dep_jbt_pcf.called_flag)
+		return 0;
+
+	if (!resume_dep_jbt_glamo.called_flag)
+		return 0;
+
+	return 1;
+}
+
+/* register jbt resume action to be dependent on pcf50633 and glamo resume */
+
+static void gta02_jbt6k74_suspending(int devindex, struct spi_device *spi)
+{
+	void jbt6k74_resume(void *spi); /* little white lies about types */
+
+	resume_dep_jbt_pcf.callback = jbt6k74_resume;
+	resume_dep_jbt_pcf.context = (void *)spi;
+	pcf50633_register_resume_dependency(pcf50633_global,
+							   &resume_dep_jbt_pcf);
+	resume_dep_jbt_glamo.callback = jbt6k74_resume;
+	resume_dep_jbt_glamo.context = (void *)spi;
+	glamo_register_resume_dependency(&resume_dep_jbt_glamo);
+}
+
+
 const struct jbt6k74_platform_data jbt6k74_pdata = {
 	.reset		= gta02_jbt6k74_reset,
 	.resuming	= gta02_jbt6k74_resuming,
+	.suspending	= gta02_jbt6k74_suspending,
+	.all_dependencies_resumed = gta02_jbt6k74_all_dependencies_resumed,
 };
 
 static struct spi_board_info gta02_spi_board_info[] = {
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index ec6b9f1..2f9b9e1 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -1937,7 +1937,7 @@ static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind)
 
 	pcf50633_global = data;
 
-	init_resume_dependency_list(data->resume_dependency);
+	init_resume_dependency_list(&data->resume_dependency);
 
 	populate_sysfs_group(data);
 
@@ -2153,11 +2153,11 @@ int pcf50633_report_resumers(struct pcf50633_data *pcf, char *buf)
  */
 
 void pcf50633_register_resume_dependency(struct pcf50633_data *pcf,
-					struct pcf50633_resume_dependency *dep)
+					struct resume_dependency *dep)
 {
-	register_resume_dependency(pcf->resume_dependency, dep);
+	register_resume_dependency(&pcf->resume_dependency, dep);
 }
-EXPORT_SYMBOL_GPL(pcf50633_register_resume_dep);
+EXPORT_SYMBOL_GPL(pcf50633_register_resume_dependency);
 
 
 static int pcf50633_suspend(struct device *dev, pm_message_t state)
@@ -2251,9 +2251,6 @@ static int pcf50633_resume(struct device *dev)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct pcf50633_data *pcf = i2c_get_clientdata(client);
 	int i;
-	struct list_head *pos, *q;
-	struct pcf50633_resume_dependency *dep;
-
 
 	mutex_lock(&pcf->lock);
 
@@ -2281,10 +2278,6 @@ static int pcf50633_resume(struct device *dev)
 		__reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
 		__reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
 		__reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
-	} else { /* force backlight down, platform will restore later */
-		__reg_write(pcf, PCF50633_REG_LEDOUT, 2);
-		__reg_write(pcf, PCF50633_REG_LEDENA, 0x20);
-		__reg_write(pcf, PCF50633_REG_LEDDIM, 1);
 	}
 
 	/* FIXME: one big read? */
@@ -2298,7 +2291,7 @@ static int pcf50633_resume(struct device *dev)
 
 	pcf50633_irq(pcf->irq, pcf);
 
-	callback_all_resume_dependencies(pcf->resume_dependency);
+	callback_all_resume_dependencies(&pcf->resume_dependency);
 
 	return 0;
 }
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
index a6b977b..445ff24 100644
--- a/drivers/mfd/glamo/glamo-core.c
+++ b/drivers/mfd/glamo/glamo-core.c
@@ -1088,6 +1088,8 @@ static int __init glamo_probe(struct platform_device *pdev)
 		goto out_free;
 	}
 
+	init_resume_dependency_list(&glamo->resume_dependency);
+
 	/* register a number of sibling devices whoise IOMEM resources
 	 * are siblings of pdev's IOMEM resource */
 #if 0
@@ -1226,6 +1228,18 @@ static int glamo_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
+
+/* have to export this because struct glamo_core is opaque */
+
+void glamo_register_resume_dependency(struct resume_dependency *
+							      resume_dependency)
+{
+	register_resume_dependency(&glamo_handle->resume_dependency,
+							     resume_dependency);
+}
+EXPORT_SYMBOL_GPL(glamo_register_resume_dependency);
+
+
 static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	glamo_power(glamo_handle, GLAMO_POWER_SUSPEND);
@@ -1235,6 +1249,8 @@ static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
 static int glamo_resume(struct platform_device *pdev)
 {
 	glamo_power(glamo_handle, GLAMO_POWER_ON);
+	callback_all_resume_dependencies(&glamo_handle->resume_dependency);
+
 	return 0;
 }
 #else
diff --git a/drivers/mfd/glamo/glamo-core.h b/drivers/mfd/glamo/glamo-core.h
index cf89f03..1fee059 100644
--- a/drivers/mfd/glamo/glamo-core.h
+++ b/drivers/mfd/glamo/glamo-core.h
@@ -2,7 +2,7 @@
 #define __GLAMO_CORE_H
 
 #include <asm/system.h>
-
+#include <linux/resume-dependency.h>
 
 /* for the time being, we put the on-screen framebuffer into the lowest
  * VRAM space.  This should make the code easily compatible with the various
@@ -29,6 +29,7 @@ struct glamo_core {
 	u_int16_t type;
 	u_int16_t revision;
 	spinlock_t lock;
+	struct resume_dependency resume_dependency;
 };
 
 struct glamo_script {
diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
index 178e2da..8e7bf36 100644
--- a/drivers/video/display/jbt6k74.c
+++ b/drivers/video/display/jbt6k74.c
@@ -27,11 +27,8 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
-#include <linux/workqueue.h>
 #include <linux/jbt6k74.h>
 
-#include <linux/spi/spi.h>
-
 enum jbt_register {
 	JBT_REG_SLEEP_IN		= 0x10,
 	JBT_REG_SLEEP_OUT		= 0x11,
@@ -116,14 +113,12 @@ struct jbt_info {
 	struct mutex lock;		/* protects tx_buf and reg_cache */
 	u16 tx_buf[8];
 	u16 reg_cache[0xEE];
-	struct work_struct work;
+	int have_resumed;
 };
 
 #define JBT_COMMAND	0x000
 #define JBT_DATA	0x100
 
-static void jbt_resume_work(struct work_struct *work);
-
 
 static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
 {
@@ -576,8 +571,6 @@ static int __devinit jbt_probe(struct spi_device *spi)
 	if (!jbt)
 		return -ENOMEM;
 
-	INIT_WORK(&jbt->work, jbt_resume_work);
-
 	jbt->spi_dev = spi;
 	jbt->state = JBT_STATE_DEEP_STANDBY;
 	mutex_init(&jbt->lock);
@@ -635,27 +628,48 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state)
 	struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
 	struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data;
 
+	/* platform needs to register resume dependencies here */
+	if (jbt6k74_pdata->suspending)
+		(jbt6k74_pdata->suspending)(0, spi);
+
 	/* Save mode for resume */
 	jbt->last_state = jbt->state;
 	jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
 
-	(jbt6k74_pdata->reset)(0, 0);
+	jbt->have_resumed = 0;
+
+//	(jbt6k74_pdata->reset)(0, 0);
 
 	return 0;
 }
 
-static void jbt_resume_work(struct work_struct *work)
+int jbt6k74_resume(struct spi_device *spi)
 {
-	struct jbt_info *jbt = container_of(work, struct jbt_info, work);
-	struct jbt6k74_platform_data *jbt6k74_pdata =
-						jbt->spi_dev->dev.platform_data;
+	struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+	struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data;
+
+	/* if we still wait on dependencies, exit because we will get called
+	 * again.  This guy will get called once by core resume action, and
+	 * should be set as resume_dependency callback for any dependencies
+	 * set by platform code.
+	 */
 
-	printk(KERN_INFO"jbt_resume_work waiting...\n");
-	/* 100ms is not enough here 2008-05-08 andy at openmoko.com
-	 * if CONFIG_PM_DEBUG is enabled 2000ms is required
+	if (jbt6k74_pdata->all_dependencies_resumed)
+		if (!(jbt6k74_pdata->all_dependencies_resumed)(0))
+			return 0;
+
+	/* we can get called twice with all dependencies resumed if our core
+	 * resume callback is last of all.  Protect against going twice
 	 */
-	msleep(400);
-	printk(KERN_INFO"jbt_resume_work GO...\n");
+	if (jbt->have_resumed)
+		return 0;
+
+	jbt->have_resumed = 1;
+
+	/* OK we are sure all devices we depend on for operation are up now */
+
+	/* even this needs glamo up on GTA02 :-/ */
+	(jbt6k74_pdata->reset)(0, 1);
 
 	jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
 	msleep(100);
@@ -675,21 +689,10 @@ static void jbt_resume_work(struct work_struct *work)
 	if (jbt6k74_pdata->resuming)
 		(jbt6k74_pdata->resuming)(0);
 
-	printk(KERN_INFO"jbt_resume_work done...\n");
-}
-
-static int jbt_resume(struct spi_device *spi)
-{
-	struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
-	struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data;
-
-	(jbt6k74_pdata->reset)(0, 1);
-
-	if (!schedule_work(&jbt->work))
-		dev_err(&spi->dev, "Unable to schedule LCM wakeup work\n");
-
 	return 0;
 }
+EXPORT_SYMBOL_GPL(jbt6k74_resume);
+
 #else
 #define jbt_suspend	NULL
 #define jbt_resume	NULL
@@ -704,7 +707,7 @@ static struct spi_driver jbt6k74_driver = {
 	.probe	 = jbt_probe,
 	.remove	 = __devexit_p(jbt_remove),
 	.suspend = jbt_suspend,
-	.resume	 = jbt_resume,
+	.resume	 = jbt6k74_resume,
 };
 
 static int __init jbt_init(void)
diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h
index 51bf593..bb4ed0a 100644
--- a/include/linux/glamofb.h
+++ b/include/linux/glamofb.h
@@ -2,6 +2,7 @@
 #define _LINUX_GLAMOFB_H
 
 #include <linux/spi/glamo.h>
+#include <linux/resume-dependency.h>
 
 struct glamofb_val {
 	unsigned int defval;
@@ -36,5 +37,7 @@ struct glamofb_platform_data {
 int glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
 int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
 void glamo_lcm_reset(int level);
+extern void
+glamo_register_resume_dependency(struct resume_dependency * resume_dependency);
 
 #endif
diff --git a/include/linux/jbt6k74.h b/include/linux/jbt6k74.h
index 0ac9124..f0eaf39 100644
--- a/include/linux/jbt6k74.h
+++ b/include/linux/jbt6k74.h
@@ -1,9 +1,13 @@
 #ifndef __JBT6K74_H__
 #define __JBT6K74_H__
 
+#include <linux/spi/spi.h>
+
 struct jbt6k74_platform_data {
 	void (*reset)(int devindex, int level);
 	void (*resuming)(int devindex); /* called when LCM is resumed */
+	void (*suspending)(int devindex, struct spi_device *spi);
+	int (*all_dependencies_resumed)(int devindex);
 };
 
 #endif
diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h
index 2bef616..8a75b28 100644
--- a/include/linux/pcf50633.h
+++ b/include/linux/pcf50633.h
@@ -127,7 +127,7 @@ pcf50633_report_resumers(struct pcf50633_data *pcf, char *buf);
 
 extern void
 pcf50633_register_resume_dependency(struct pcf50633_data *pcf,
-					struct pcf50633_resume_dependency *dep);
+					struct resume_dependency *dep);
 
 
 #define PCF50633_FEAT_EXTON	0x00000001	/* not yet supported */
diff --git a/include/linux/resume-dependency.h b/include/linux/resume-dependency.h
index b13aa3e..e0c0f33 100644
--- a/include/linux/resume-dependency.h
+++ b/include/linux/resume-dependency.h
@@ -38,7 +38,7 @@ struct resume_dependency {
  */
 
 #define init_resume_dependency_list(_head) \
-	INIT_LIST_HEAD(&_head.list);
+	INIT_LIST_HEAD(&(_head)->list);
 
 
 /* if your resume function depends on something else being resumed first, you
@@ -48,8 +48,8 @@ struct resume_dependency {
  */
 
 #define register_resume_dependency(_head, _dep) { \
-	_dep->called_flag = 0; \
-	list_add(&_dep->list, &_head->list); \
+	(_dep)->called_flag = 0; \
+	list_add(&(_dep)->list, &(_head)->list); \
 }
 
 /* In the resume function that things can be dependent on, at the end you
@@ -61,10 +61,10 @@ struct resume_dependency {
 	struct list_head *_pos, *_q; \
 	struct resume_dependency *_dep; \
 \
-	list_for_each_safe(pos, _q, &_head.list) { \
+	list_for_each_safe(_pos, _q, &((_head)->list)) { \
 		_dep = list_entry(_pos, struct resume_dependency, list); \
 		_dep->called_flag = 1; \
-		(_dep->callback)(dep->context); \
+		(_dep->callback)(_dep->context); \
 		list_del(_pos); \
 	} \
 }





More information about the openmoko-kernel mailing list