summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Wylder <jwylder1@motorola.com>2014-04-02 16:04:15 -0500
committerJames Wylder <jwylder@motorola.com>2014-04-30 19:20:36 +0000
commitc4494c4ed1458d628b0f8f9b4d29a854dc9fa2e2 (patch)
treeaff10bca6de9ab7814b4b3d387a5c58de8efbb6f
parent8841acf3be932ebc1ca5a3004b6dba5ae787f890 (diff)
downloadolio-linux-3.10-c4494c4ed1458d628b0f8f9b4d29a854dc9fa2e2.tar.xz
olio-linux-3.10-c4494c4ed1458d628b0f8f9b4d29a854dc9fa2e2.zip
IKXCLOCK-639 tps65912: irq handler accesses spi bus too early
Late is suspend and early in resume, the irq handler for the tps69512 driver will attempt to access the spi bus to determine the origin of the interrupt. This may happen before the spi bus is resumed. Force the handler to delay until the associated spi device has been resumed. Change-Id: Ie38185490d8da9555c3092f543b0c495d1de5782 Signed-off-by: Jim Wylder <jwylder1@motorola.com>
-rw-r--r--drivers/mfd/tps65912-irq.c4
-rw-r--r--drivers/mfd/tps65912-spi.c23
-rw-r--r--include/linux/mfd/tps65912.h1
3 files changed, 28 insertions, 0 deletions
diff --git a/drivers/mfd/tps65912-irq.c b/drivers/mfd/tps65912-irq.c
index 96e7b6a34b0..110d714421b 100644
--- a/drivers/mfd/tps65912-irq.c
+++ b/drivers/mfd/tps65912-irq.c
@@ -81,6 +81,7 @@ static irqreturn_t tps65912_irq(int irq, void *irq_data)
int i;
pr_debug("tps65912 handle irq %d\n", irq);
+ mutex_lock(&tps65912->pm_lock);
tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
irq_sts = reg;
@@ -93,6 +94,7 @@ static irqreturn_t tps65912_irq(int irq, void *irq_data)
irq_sts &= ~tps65912->irq_mask;
if (!irq_sts) {
+ mutex_unlock(&tps65912->pm_lock);
pr_debug("tps65912 %d IRQ_NONE\n", irq);
return IRQ_NONE;
}
@@ -121,6 +123,8 @@ static irqreturn_t tps65912_irq(int irq, void *irq_data)
if (reg)
tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
+ mutex_unlock(&tps65912->pm_lock);
+
pr_debug("tps65912 %d IRQ_HANDLED\n", irq);
return IRQ_HANDLED;
}
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
index bf520899b13..922cc482ff4 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -103,6 +103,8 @@ static int tps65912_spi_probe(struct spi_device *spi)
tps65912->read = tps65912_spi_read;
tps65912->write = tps65912_spi_write;
+ mutex_init(&tps65912->pm_lock);
+
spi_set_drvdata(spi, tps65912);
return tps65912_device_init(tps65912);
@@ -117,9 +119,30 @@ static int tps65912_spi_remove(struct spi_device *spi)
return 0;
}
+int tps65912_spi_suspend_late(struct device *dev)
+{
+ struct tps65912 *tps65912 = dev_get_drvdata(dev);
+ if (tps65912)
+ mutex_lock(&tps65912->pm_lock);
+ return 0;
+}
+int tps65912_spi_resume_early(struct device *dev)
+{
+ struct tps65912 *tps65912 = dev_get_drvdata(dev);
+ if (tps65912)
+ mutex_unlock(&tps65912->pm_lock);
+ return 0;
+}
+
+static struct dev_pm_ops tps65912_pm_ops = {
+ .suspend_late = tps65912_spi_suspend_late,
+ .resume_early = tps65912_spi_resume_early,
+};
+
static struct spi_driver tps65912_spi_driver = {
.driver = {
.name = "tps65912",
+ .pm = &tps65912_pm_ops,
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(tps65912_of_match),
diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h
index 4243323b1e9..c32637166f2 100644
--- a/include/linux/mfd/tps65912.h
+++ b/include/linux/mfd/tps65912.h
@@ -334,6 +334,7 @@ struct tps65912 {
u32 powerkey_code;
u32 powerkey_up_irq;
u32 powerkey_down_irq;
+ struct mutex pm_lock; /* guard access to spi bus from irq */
};
struct tps65912_platform_data {