[PATCHv9 07/18] mfd: omap-prm: added suspend prepare and complete callbacks

From: Tero Kristo
Date: Fri Sep 23 2011 - 08:48:38 EST


These are needed because runtime PM is disabled during suspend, and
it is bad if we get interrupts from the PRCM chain handler during it.
Now, PRCM interrupt forwarding is disabled until the suspend->complete,
which makes sure that all the needed drivers are up.

Signed-off-by: Tero Kristo <t-kristo@xxxxxx>
Cc: Kevin Hilman <khilman@xxxxxx>
Cc: Paul Walmsley <paul@xxxxxxxxx>
Cc: Samuel Ortiz <sameo@xxxxxxxxxxxxxxx>
---
drivers/mfd/omap-prm-common.c | 34 +++++++++++++++++++++++++++++++++-
drivers/mfd/omap-prm.h | 2 ++
drivers/mfd/omap3xxx-prm.c | 1 +
drivers/mfd/omap4xxx-prm.c | 1 +
4 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/drivers/mfd/omap-prm-common.c b/drivers/mfd/omap-prm-common.c
index 2886eb2..e8522fc 100644
--- a/drivers/mfd/omap-prm-common.c
+++ b/drivers/mfd/omap-prm-common.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/platform_device.h>

#include "omap-prm.h"

@@ -35,6 +36,7 @@ struct omap_prm_device {
int base_irq;
int irq;
void __iomem *base;
+ int suspended;
};

static struct omap_prm_device prm_dev;
@@ -92,12 +94,20 @@ static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
struct irq_chip *chip = irq_desc_get_chip(desc);
unsigned int virtirq;
int nr_irqs = prm_dev.irq_setup->nr_regs * 32;
+ int i;
+
+ if (prm_dev.suspended)
+ for (i = 0; i < prm_dev.irq_setup->nr_regs; i++) {
+ prm_dev.saved_mask[i] =
+ prm_read_reg(prm_dev.irq_setup->mask + i * 4);
+ prm_write_reg(0, prm_dev.irq_setup->mask + i * 4);
+ }

/*
* Loop until all pending irqs are handled, since
* generic_handle_irq() can cause new irqs to come
*/
- while (1) {
+ while (!prm_dev.suspended) {
prm_pending_events(pending);

/* No bit set, then all IRQs are handled */
@@ -258,6 +268,28 @@ err:
return -ENOMEM;
}

+static int omap_prm_prepare(struct device *kdev)
+{
+ prm_dev.suspended = 1;
+ return 0;
+}
+
+static void omap_prm_complete(struct device *kdev)
+{
+ int i;
+
+ prm_dev.suspended = 0;
+
+ for (i = 0; i < prm_dev.irq_setup->nr_regs; i++)
+ prm_write_reg(prm_dev.saved_mask[i],
+ prm_dev.irq_setup->mask + i * 4);
+}
+
+const struct dev_pm_ops omap_prm_pm_ops = {
+ .prepare = omap_prm_prepare,
+ .complete = omap_prm_complete,
+};
+
MODULE_AUTHOR("Tero Kristo <t-kristo@xxxxxx>");
MODULE_DESCRIPTION("OMAP PRM core driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/omap-prm.h b/drivers/mfd/omap-prm.h
index 7ffefe1..c901810 100644
--- a/drivers/mfd/omap-prm.h
+++ b/drivers/mfd/omap-prm.h
@@ -32,6 +32,8 @@ struct omap_prcm_irq {
.priority = _priority \
}

+extern const struct dev_pm_ops omap_prm_pm_ops;
+
void omap_prcm_irq_cleanup(void);
int omap_prcm_register_chain_handler(int irq, void __iomem *base,
const struct omap_prcm_irq_setup *irq_setup,
diff --git a/drivers/mfd/omap3xxx-prm.c b/drivers/mfd/omap3xxx-prm.c
index 9be21ee..38b88aa 100644
--- a/drivers/mfd/omap3xxx-prm.c
+++ b/drivers/mfd/omap3xxx-prm.c
@@ -66,6 +66,7 @@ static struct platform_driver omap3xxx_prm_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
+ .pm = &omap_prm_pm_ops,
},
};

diff --git a/drivers/mfd/omap4xxx-prm.c b/drivers/mfd/omap4xxx-prm.c
index 6e134a7..92cc67d 100644
--- a/drivers/mfd/omap4xxx-prm.c
+++ b/drivers/mfd/omap4xxx-prm.c
@@ -65,6 +65,7 @@ static struct platform_driver omap4xxx_prm_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
+ .pm = &omap_prm_pm_ops,
},
};

--
1.7.4.1


Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/