MTD PM Resume

Todd Poynor tpoynor at mvista.com
Fri Jul 1 20:51:38 EDT 2005


On Fri, Jun 03, 2005 at 06:24:34PM -0700, Todd Poynor wrote:
...
> If you initiated the suspend via a call to pm_suspend() or 
> /sys/power/state then LDM suspend/resume driver methods will be called, 
> and it looks like nothing in the mtd core will automatically register 
> drivers or devices in LDM.  There are existing examples of registering 
> with LDM in some map drivers, registering a driver with the platform 
> bus.  Looks like boards that power cycle flash chips for certain sleep 
> states need to also register a device, and add suspend/resume callbacks 
> in the struct_driver that end up calling the chip driver suspend/resume 
> methods (even if they don't use flash that powers up locked, since the 
> mtd state machine needs to be reset to assume the flash chips are in 
> ready state).  Documentation/power/devices.txt has some more info on 
> those interfaces.
> 
> Or if anybody has a better way to handle this I'm all ears.  A class 
> device for generic mtd might do it, not sure.
> 
> You just reminded me I need to figure out how to do this for a couple of 
> boards, thanks.  If there's no disagreement on the above being the 
> correct approach I'll float a patch soon.

Here's an example of how it might be done via a board mapping driver,
for the PXA27x Mainstone board.  I'm not sure if this is the ultimate in
mtd + ldm + pm integration, but it's something.  Any comments appreciated.

Index: linux-2.6.12/arch/arm/mach-pxa/mainstone.c
===================================================================
--- linux-2.6.12.orig/arch/arm/mach-pxa/mainstone.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/arch/arm/mach-pxa/mainstone.c	2005-07-02 00:33:23.000000000 +0000
@@ -189,6 +189,11 @@
 	.dev		= { .platform_data = &mst_audio_ops },
 };
 
+static struct platform_device mainstone_flash_device = {
+	.name		= "mainstone-flash",
+	.id		= -1,
+};
+
 static void mainstone_backlight_power(int on)
 {
 	if (on) {
@@ -304,6 +309,7 @@
 
 	platform_device_register(&smc91x_device);
 	platform_device_register(&mst_audio_device);
+	platform_device_register(&mainstone_flash_device);
 
 	/* reading Mainstone's "Virtual Configuration Register"
 	   might be handy to select LCD type here */
Index: linux-2.6.12/drivers/mtd/maps/mainstone-flash.c
===================================================================
--- linux-2.6.12.orig/drivers/mtd/maps/mainstone-flash.c	2005-07-01 22:22:30.000000000 +0000
+++ linux-2.6.12/drivers/mtd/maps/mainstone-flash.c	2005-07-02 00:35:56.000000000 +0000
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
@@ -69,7 +70,8 @@
 
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
-static int __init init_mainstone(void)
+
+static int __init mainstone_flash_probe(struct device *_dev)
 {
 	int SW7 = 0;  /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
 	int ret = 0, i;
@@ -147,10 +149,11 @@
 			add_mtd_device(mymtds[i]);
 		}
 	}
+
 	return 0;
 }
 
-static void __exit cleanup_mainstone(void)
+static int mainstone_flash_remove(struct device *_dev)
 {
 	int i;
 	for (i = 0; i < 2; i++) {
@@ -168,6 +171,59 @@
 			iounmap(mainstone_maps[i].cached);
 		kfree(parsed_parts[i]);
 	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int mainstone_flash_suspend(struct device *dev, u32 state, u32 level)
+{
+	int i;
+
+	if (level == SUSPEND_DISABLE) {
+		for (i = 0; i < 2; i++)
+			if (mymtds[i] && mymtds[i]->suspend)
+				mymtds[i]->suspend(mymtds[i]);
+	}
+
+	return 0;
+}
+
+static int mainstone_flash_resume(struct device *dev, u32 level)
+{
+	int i;
+
+	if (level == RESUME_ENABLE) {
+		for (i = 0; i < 2; i++)
+			if (mymtds[i] && mymtds[i]->resume)
+				mymtds[i]->resume(mymtds[i]);
+
+	}
+	return 0;
+}
+
+#endif
+
+static struct device_driver mainstone_flash_driver = {
+	.name		= "mainstone-flash",
+	.bus		= &platform_bus_type,
+	.probe		= &mainstone_flash_probe,
+	.remove		= &mainstone_flash_remove,
+#ifdef CONFIG_PM
+	.suspend	= &mainstone_flash_suspend,
+	.resume		= &mainstone_flash_resume,
+#endif
+};
+
+static int __init init_mainstone(void)
+{
+	return driver_register(&mainstone_flash_driver);
+}
+
+static void __exit cleanup_mainstone(void)
+{
+	driver_unregister(&mainstone_flash_driver);
 }
 
 module_init(init_mainstone);




More information about the linux-mtd mailing list