aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/pl330.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/pl330.c')
-rw-r--r--drivers/dma/pl330.c99
1 files changed, 95 insertions, 4 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 025b905f6db2..bdf40b530032 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -27,6 +27,7 @@
27#include <linux/of.h> 27#include <linux/of.h>
28#include <linux/of_dma.h> 28#include <linux/of_dma.h>
29#include <linux/err.h> 29#include <linux/err.h>
30#include <linux/pm_runtime.h>
30 31
31#include "dmaengine.h" 32#include "dmaengine.h"
32#define PL330_MAX_CHAN 8 33#define PL330_MAX_CHAN 8
@@ -265,6 +266,9 @@ static unsigned cmd_line;
265 266
266#define NR_DEFAULT_DESC 16 267#define NR_DEFAULT_DESC 16
267 268
269/* Delay for runtime PM autosuspend, ms */
270#define PL330_AUTOSUSPEND_DELAY 20
271
268/* Populated by the PL330 core driver for DMA API driver's info */ 272/* Populated by the PL330 core driver for DMA API driver's info */
269struct pl330_config { 273struct pl330_config {
270 u32 periph_id; 274 u32 periph_id;
@@ -1958,6 +1962,7 @@ static void pl330_tasklet(unsigned long data)
1958 struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; 1962 struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
1959 struct dma_pl330_desc *desc, *_dt; 1963 struct dma_pl330_desc *desc, *_dt;
1960 unsigned long flags; 1964 unsigned long flags;
1965 bool power_down = false;
1961 1966
1962 spin_lock_irqsave(&pch->lock, flags); 1967 spin_lock_irqsave(&pch->lock, flags);
1963 1968
@@ -1972,10 +1977,17 @@ static void pl330_tasklet(unsigned long data)
1972 /* Try to submit a req imm. next to the last completed cookie */ 1977 /* Try to submit a req imm. next to the last completed cookie */
1973 fill_queue(pch); 1978 fill_queue(pch);
1974 1979
1975 /* Make sure the PL330 Channel thread is active */ 1980 if (list_empty(&pch->work_list)) {
1976 spin_lock(&pch->thread->dmac->lock); 1981 spin_lock(&pch->thread->dmac->lock);
1977 _start(pch->thread); 1982 _stop(pch->thread);
1978 spin_unlock(&pch->thread->dmac->lock); 1983 spin_unlock(&pch->thread->dmac->lock);
1984 power_down = true;
1985 } else {
1986 /* Make sure the PL330 Channel thread is active */
1987 spin_lock(&pch->thread->dmac->lock);
1988 _start(pch->thread);
1989 spin_unlock(&pch->thread->dmac->lock);
1990 }
1979 1991
1980 while (!list_empty(&pch->completed_list)) { 1992 while (!list_empty(&pch->completed_list)) {
1981 dma_async_tx_callback callback; 1993 dma_async_tx_callback callback;
@@ -1990,6 +2002,12 @@ static void pl330_tasklet(unsigned long data)
1990 if (pch->cyclic) { 2002 if (pch->cyclic) {
1991 desc->status = PREP; 2003 desc->status = PREP;
1992 list_move_tail(&desc->node, &pch->work_list); 2004 list_move_tail(&desc->node, &pch->work_list);
2005 if (power_down) {
2006 spin_lock(&pch->thread->dmac->lock);
2007 _start(pch->thread);
2008 spin_unlock(&pch->thread->dmac->lock);
2009 power_down = false;
2010 }
1993 } else { 2011 } else {
1994 desc->status = FREE; 2012 desc->status = FREE;
1995 list_move_tail(&desc->node, &pch->dmac->desc_pool); 2013 list_move_tail(&desc->node, &pch->dmac->desc_pool);
@@ -2004,6 +2022,12 @@ static void pl330_tasklet(unsigned long data)
2004 } 2022 }
2005 } 2023 }
2006 spin_unlock_irqrestore(&pch->lock, flags); 2024 spin_unlock_irqrestore(&pch->lock, flags);
2025
2026 /* If work list empty, power down */
2027 if (power_down) {
2028 pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
2029 pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
2030 }
2007} 2031}
2008 2032
2009bool pl330_filter(struct dma_chan *chan, void *param) 2033bool pl330_filter(struct dma_chan *chan, void *param)
@@ -2073,6 +2097,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
2073 2097
2074 switch (cmd) { 2098 switch (cmd) {
2075 case DMA_TERMINATE_ALL: 2099 case DMA_TERMINATE_ALL:
2100 pm_runtime_get_sync(pl330->ddma.dev);
2076 spin_lock_irqsave(&pch->lock, flags); 2101 spin_lock_irqsave(&pch->lock, flags);
2077 2102
2078 spin_lock(&pl330->lock); 2103 spin_lock(&pl330->lock);
@@ -2099,10 +2124,15 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
2099 dma_cookie_complete(&desc->txd); 2124 dma_cookie_complete(&desc->txd);
2100 } 2125 }
2101 2126
2127 if (!list_empty(&pch->work_list))
2128 pm_runtime_put(pl330->ddma.dev);
2129
2102 list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool); 2130 list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool);
2103 list_splice_tail_init(&pch->work_list, &pl330->desc_pool); 2131 list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
2104 list_splice_tail_init(&pch->completed_list, &pl330->desc_pool); 2132 list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
2105 spin_unlock_irqrestore(&pch->lock, flags); 2133 spin_unlock_irqrestore(&pch->lock, flags);
2134 pm_runtime_mark_last_busy(pl330->ddma.dev);
2135 pm_runtime_put_autosuspend(pl330->ddma.dev);
2106 break; 2136 break;
2107 case DMA_SLAVE_CONFIG: 2137 case DMA_SLAVE_CONFIG:
2108 slave_config = (struct dma_slave_config *)arg; 2138 slave_config = (struct dma_slave_config *)arg;
@@ -2138,6 +2168,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
2138 2168
2139 tasklet_kill(&pch->task); 2169 tasklet_kill(&pch->task);
2140 2170
2171 pm_runtime_get_sync(pch->dmac->ddma.dev);
2141 spin_lock_irqsave(&pch->lock, flags); 2172 spin_lock_irqsave(&pch->lock, flags);
2142 2173
2143 pl330_release_channel(pch->thread); 2174 pl330_release_channel(pch->thread);
@@ -2147,6 +2178,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
2147 list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); 2178 list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
2148 2179
2149 spin_unlock_irqrestore(&pch->lock, flags); 2180 spin_unlock_irqrestore(&pch->lock, flags);
2181 pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
2182 pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
2150} 2183}
2151 2184
2152static enum dma_status 2185static enum dma_status
@@ -2162,6 +2195,15 @@ static void pl330_issue_pending(struct dma_chan *chan)
2162 unsigned long flags; 2195 unsigned long flags;
2163 2196
2164 spin_lock_irqsave(&pch->lock, flags); 2197 spin_lock_irqsave(&pch->lock, flags);
2198 if (list_empty(&pch->work_list)) {
2199 /*
2200 * Warn on nothing pending. Empty submitted_list may
2201 * break our pm_runtime usage counter as it is
2202 * updated on work_list emptiness status.
2203 */
2204 WARN_ON(list_empty(&pch->submitted_list));
2205 pm_runtime_get_sync(pch->dmac->ddma.dev);
2206 }
2165 list_splice_tail_init(&pch->submitted_list, &pch->work_list); 2207 list_splice_tail_init(&pch->submitted_list, &pch->work_list);
2166 spin_unlock_irqrestore(&pch->lock, flags); 2208 spin_unlock_irqrestore(&pch->lock, flags);
2167 2209
@@ -2594,6 +2636,46 @@ static int pl330_dma_device_slave_caps(struct dma_chan *dchan,
2594 return 0; 2636 return 0;
2595} 2637}
2596 2638
2639/*
2640 * Runtime PM callbacks are provided by amba/bus.c driver.
2641 *
2642 * It is assumed here that IRQ safe runtime PM is chosen in probe and amba
2643 * bus driver will only disable/enable the clock in runtime PM callbacks.
2644 */
2645static int __maybe_unused pl330_suspend(struct device *dev)
2646{
2647 struct amba_device *pcdev = to_amba_device(dev);
2648
2649 pm_runtime_disable(dev);
2650
2651 if (!pm_runtime_status_suspended(dev)) {
2652 /* amba did not disable the clock */
2653 amba_pclk_disable(pcdev);
2654 }
2655 amba_pclk_unprepare(pcdev);
2656
2657 return 0;
2658}
2659
2660static int __maybe_unused pl330_resume(struct device *dev)
2661{
2662 struct amba_device *pcdev = to_amba_device(dev);
2663 int ret;
2664
2665 ret = amba_pclk_prepare(pcdev);
2666 if (ret)
2667 return ret;
2668
2669 if (!pm_runtime_status_suspended(dev))
2670 ret = amba_pclk_enable(pcdev);
2671
2672 pm_runtime_enable(dev);
2673
2674 return ret;
2675}
2676
2677static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume);
2678
2597static int 2679static int
2598pl330_probe(struct amba_device *adev, const struct amba_id *id) 2680pl330_probe(struct amba_device *adev, const struct amba_id *id)
2599{ 2681{
@@ -2748,6 +2830,12 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2748 pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan, 2830 pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan,
2749 pcfg->num_peri, pcfg->num_events); 2831 pcfg->num_peri, pcfg->num_events);
2750 2832
2833 pm_runtime_irq_safe(&adev->dev);
2834 pm_runtime_use_autosuspend(&adev->dev);
2835 pm_runtime_set_autosuspend_delay(&adev->dev, PL330_AUTOSUSPEND_DELAY);
2836 pm_runtime_mark_last_busy(&adev->dev);
2837 pm_runtime_put_autosuspend(&adev->dev);
2838
2751 return 0; 2839 return 0;
2752probe_err3: 2840probe_err3:
2753 /* Idle the DMAC */ 2841 /* Idle the DMAC */
@@ -2774,6 +2862,8 @@ static int pl330_remove(struct amba_device *adev)
2774 struct pl330_dmac *pl330 = amba_get_drvdata(adev); 2862 struct pl330_dmac *pl330 = amba_get_drvdata(adev);
2775 struct dma_pl330_chan *pch, *_p; 2863 struct dma_pl330_chan *pch, *_p;
2776 2864
2865 pm_runtime_get_noresume(pl330->ddma.dev);
2866
2777 if (adev->dev.of_node) 2867 if (adev->dev.of_node)
2778 of_dma_controller_free(adev->dev.of_node); 2868 of_dma_controller_free(adev->dev.of_node);
2779 2869
@@ -2812,6 +2902,7 @@ static struct amba_driver pl330_driver = {
2812 .drv = { 2902 .drv = {
2813 .owner = THIS_MODULE, 2903 .owner = THIS_MODULE,
2814 .name = "dma-pl330", 2904 .name = "dma-pl330",
2905 .pm = &pl330_pm,
2815 }, 2906 },
2816 .id_table = pl330_ids, 2907 .id_table = pl330_ids,
2817 .probe = pl330_probe, 2908 .probe = pl330_probe,