cpcap: suspend/resume
authorTodd Poynor <toddpoynor@google.com>
Thu, 5 Aug 2010 03:25:59 +0000 (20:25 -0700)
committerColin Cross <ccross@android.com>
Wed, 6 Oct 2010 23:33:33 +0000 (16:33 -0700)
Disable cpcap interrupts at suspend and re-enable at resume, to avoid
processing interrupts while the SPI controller is suspended.

Change-Id: I26676b8ce8983bf5477f169a15d811c474c6f5a4
Signed-off-by: Todd Poynor <toddpoynor@google.com>
drivers/mfd/cpcap-core.c
drivers/mfd/cpcap-irq.c
include/linux/spi/cpcap.h

index 78b4fbb9efc38b9b9b40444528233feeddcfdb39..5015e390b77f5d8ced6fa5e2577d31f892f9e4bd 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/reboot.h>
 #include <linux/notifier.h>
 #include <linux/delay.h>
+#include <linux/pm.h>
 
 struct cpcap_driver_info {
        struct list_head list;
@@ -38,6 +39,11 @@ static int ioctl(struct inode *inode,
 static int __devinit cpcap_probe(struct spi_device *spi);
 static int __devexit cpcap_remove(struct spi_device *spi);
 
+#ifdef CONFIG_PM
+static int cpcap_suspend(struct spi_device *spi, pm_message_t mesg);
+static int cpcap_resume(struct spi_device *spi);
+#endif
+
 const static struct file_operations cpcap_fops = {
        .owner = THIS_MODULE,
        .ioctl = ioctl,
@@ -57,6 +63,10 @@ static struct spi_driver cpcap_driver = {
                   },
        .probe = cpcap_probe,
        .remove = __devexit_p(cpcap_remove),
+#ifdef CONFIG_PM
+       .suspend = cpcap_suspend,
+       .resume = cpcap_resume,
+#endif
 };
 
 static struct platform_device cpcap_adc_device = {
@@ -455,6 +465,23 @@ static void cpcap_shutdown(void)
        spi_unregister_driver(&cpcap_driver);
 }
 
+#ifdef CONFIG_PM
+static int cpcap_suspend(struct spi_device *spi, pm_message_t mesg)
+{
+
+       struct cpcap_device *cpcap = spi_get_drvdata(spi);
+
+       return cpcap_irq_suspend(cpcap);
+}
+
+static int cpcap_resume(struct spi_device *spi)
+{
+       struct cpcap_device *cpcap = spi_get_drvdata(spi);
+
+       return cpcap_irq_resume(cpcap);
+}
+#endif
+
 subsys_initcall(cpcap_init);
 module_exit(cpcap_shutdown);
 
index 9c133be6812601f7323533e371e4ff0170c51c6e..397caaae20a75f21b0b648c07bd53e5febd6856a 100644 (file)
@@ -630,3 +630,21 @@ int cpcap_irq_sense(struct cpcap_device *cpcap,
        return ((val & EVENT_MASK(irq)) != 0) ? 1 : 0;
 }
 EXPORT_SYMBOL_GPL(cpcap_irq_sense);
+
+#ifdef CONFIG_PM
+int cpcap_irq_suspend(struct cpcap_device *cpcap)
+{
+       struct spi_device *spi = cpcap->spi;
+
+       disable_irq(spi->irq);
+       return 0;
+}
+
+int cpcap_irq_resume(struct cpcap_device *cpcap)
+{
+       struct spi_device *spi = cpcap->spi;
+
+       enable_irq(spi->irq);
+       return 0;
+}
+#endif
index d0d82c4291ba2bce8ebb5671a5b8abd2ea88fd65..b2d9fcf303dd10bacaf4cfc7a762698f6c11638d 100644 (file)
@@ -717,6 +717,12 @@ int cpcap_irq_mask_get(struct cpcap_device *cpcap, enum cpcap_irqs int_event);
 int cpcap_irq_sense(struct cpcap_device *cpcap, enum cpcap_irqs int_event,
                    unsigned char clear);
 
+#ifdef CONFIG_PM
+int cpcap_irq_suspend(struct cpcap_device *cpcap);
+
+int cpcap_irq_resume(struct cpcap_device *cpcap);
+#endif
+
 int cpcap_adc_sync_read(struct cpcap_device *cpcap,
                        struct cpcap_adc_request *request);