diff options
-rw-r--r-- | drivers/spi/spi.c | 16 | ||||
-rw-r--r-- | include/linux/spi/spi.h | 5 |
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 978dda2c5239..361cced68069 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -553,6 +553,10 @@ static void spi_pump_messages(struct kthread_work *work) | |||
553 | master->unprepare_transfer_hardware(master)) | 553 | master->unprepare_transfer_hardware(master)) |
554 | dev_err(&master->dev, | 554 | dev_err(&master->dev, |
555 | "failed to unprepare transfer hardware\n"); | 555 | "failed to unprepare transfer hardware\n"); |
556 | if (master->auto_runtime_pm) { | ||
557 | pm_runtime_mark_last_busy(master->dev.parent); | ||
558 | pm_runtime_put_autosuspend(master->dev.parent); | ||
559 | } | ||
556 | return; | 560 | return; |
557 | } | 561 | } |
558 | 562 | ||
@@ -572,11 +576,23 @@ static void spi_pump_messages(struct kthread_work *work) | |||
572 | master->busy = true; | 576 | master->busy = true; |
573 | spin_unlock_irqrestore(&master->queue_lock, flags); | 577 | spin_unlock_irqrestore(&master->queue_lock, flags); |
574 | 578 | ||
579 | if (!was_busy && master->auto_runtime_pm) { | ||
580 | ret = pm_runtime_get_sync(master->dev.parent); | ||
581 | if (ret < 0) { | ||
582 | dev_err(&master->dev, "Failed to power device: %d\n", | ||
583 | ret); | ||
584 | return; | ||
585 | } | ||
586 | } | ||
587 | |||
575 | if (!was_busy && master->prepare_transfer_hardware) { | 588 | if (!was_busy && master->prepare_transfer_hardware) { |
576 | ret = master->prepare_transfer_hardware(master); | 589 | ret = master->prepare_transfer_hardware(master); |
577 | if (ret) { | 590 | if (ret) { |
578 | dev_err(&master->dev, | 591 | dev_err(&master->dev, |
579 | "failed to prepare transfer hardware\n"); | 592 | "failed to prepare transfer hardware\n"); |
593 | |||
594 | if (master->auto_runtime_pm) | ||
595 | pm_runtime_put(master->dev.parent); | ||
580 | return; | 596 | return; |
581 | } | 597 | } |
582 | } | 598 | } |
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 28e440be1c07..bf0204c00053 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h | |||
@@ -254,6 +254,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) | |||
254 | * @busy: message pump is busy | 254 | * @busy: message pump is busy |
255 | * @running: message pump is running | 255 | * @running: message pump is running |
256 | * @rt: whether this queue is set to run as a realtime task | 256 | * @rt: whether this queue is set to run as a realtime task |
257 | * @auto_runtime_pm: the core should ensure a runtime PM reference is held | ||
258 | * while the hardware is prepared, using the parent | ||
259 | * device for the spidev | ||
257 | * @prepare_transfer_hardware: a message will soon arrive from the queue | 260 | * @prepare_transfer_hardware: a message will soon arrive from the queue |
258 | * so the subsystem requests the driver to prepare the transfer hardware | 261 | * so the subsystem requests the driver to prepare the transfer hardware |
259 | * by issuing this call | 262 | * by issuing this call |
@@ -374,11 +377,13 @@ struct spi_master { | |||
374 | bool busy; | 377 | bool busy; |
375 | bool running; | 378 | bool running; |
376 | bool rt; | 379 | bool rt; |
380 | bool auto_runtime_pm; | ||
377 | 381 | ||
378 | int (*prepare_transfer_hardware)(struct spi_master *master); | 382 | int (*prepare_transfer_hardware)(struct spi_master *master); |
379 | int (*transfer_one_message)(struct spi_master *master, | 383 | int (*transfer_one_message)(struct spi_master *master, |
380 | struct spi_message *mesg); | 384 | struct spi_message *mesg); |
381 | int (*unprepare_transfer_hardware)(struct spi_master *master); | 385 | int (*unprepare_transfer_hardware)(struct spi_master *master); |
386 | |||
382 | /* gpio chip select */ | 387 | /* gpio chip select */ |
383 | int *cs_gpios; | 388 | int *cs_gpios; |
384 | }; | 389 | }; |