diff options
| author | Jim Wylder <jwylder1@motorola.com> | 2014-04-02 16:04:15 -0500 |
|---|---|---|
| committer | James Wylder <jwylder@motorola.com> | 2014-04-30 19:20:36 +0000 |
| commit | c4494c4ed1458d628b0f8f9b4d29a854dc9fa2e2 (patch) | |
| tree | aff10bca6de9ab7814b4b3d387a5c58de8efbb6f | |
| parent | 8841acf3be932ebc1ca5a3004b6dba5ae787f890 (diff) | |
| download | olio-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.c | 4 | ||||
| -rw-r--r-- | drivers/mfd/tps65912-spi.c | 23 | ||||
| -rw-r--r-- | include/linux/mfd/tps65912.h | 1 |
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, ®); 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, ®); + 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 { |