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.c106
1 files changed, 99 insertions, 7 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 19a99743cf52..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{
@@ -2619,6 +2701,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2619 return -ENOMEM; 2701 return -ENOMEM;
2620 } 2702 }
2621 2703
2704 pd = &pl330->ddma;
2705 pd->dev = &adev->dev;
2706
2622 pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0; 2707 pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
2623 2708
2624 res = &adev->res; 2709 res = &adev->res;
@@ -2655,7 +2740,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2655 if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC)) 2740 if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
2656 dev_warn(&adev->dev, "unable to allocate desc\n"); 2741 dev_warn(&adev->dev, "unable to allocate desc\n");
2657 2742
2658 pd = &pl330->ddma;
2659 INIT_LIST_HEAD(&pd->channels); 2743 INIT_LIST_HEAD(&pd->channels);
2660 2744
2661 /* Initialize channel parameters */ 2745 /* Initialize channel parameters */
@@ -2692,7 +2776,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2692 list_add_tail(&pch->chan.device_node, &pd->channels); 2776 list_add_tail(&pch->chan.device_node, &pd->channels);
2693 } 2777 }
2694 2778
2695 pd->dev = &adev->dev;
2696 if (pdat) { 2779 if (pdat) {
2697 pd->cap_mask = pdat->cap_mask; 2780 pd->cap_mask = pdat->cap_mask;
2698 } else { 2781 } else {
@@ -2747,6 +2830,12 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2747 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,
2748 pcfg->num_peri, pcfg->num_events); 2831 pcfg->num_peri, pcfg->num_events);
2749 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
2750 return 0; 2839 return 0;
2751probe_err3: 2840probe_err3:
2752 /* Idle the DMAC */ 2841 /* Idle the DMAC */
@@ -2773,6 +2862,8 @@ static int pl330_remove(struct amba_device *adev)
2773 struct pl330_dmac *pl330 = amba_get_drvdata(adev); 2862 struct pl330_dmac *pl330 = amba_get_drvdata(adev);
2774 struct dma_pl330_chan *pch, *_p; 2863 struct dma_pl330_chan *pch, *_p;
2775 2864
2865 pm_runtime_get_noresume(pl330->ddma.dev);
2866
2776 if (adev->dev.of_node) 2867 if (adev->dev.of_node)
2777 of_dma_controller_free(adev->dev.of_node); 2868 of_dma_controller_free(adev->dev.of_node);
2778 2869
@@ -2811,6 +2902,7 @@ static struct amba_driver pl330_driver = {
2811 .drv = { 2902 .drv = {
2812 .owner = THIS_MODULE, 2903 .owner = THIS_MODULE,
2813 .name = "dma-pl330", 2904 .name = "dma-pl330",
2905 .pm = &pl330_pm,
2814 }, 2906 },
2815 .id_table = pl330_ids, 2907 .id_table = pl330_ids,
2816 .probe = pl330_probe, 2908 .probe = pl330_probe,
@@ -2819,6 +2911,6 @@ static struct amba_driver pl330_driver = {
2819 2911
2820module_amba_driver(pl330_driver); 2912module_amba_driver(pl330_driver);
2821 2913
2822MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); 2914MODULE_AUTHOR("Jaswinder Singh <jassisinghbrar@gmail.com>");
2823MODULE_DESCRIPTION("API Driver for PL330 DMAC"); 2915MODULE_DESCRIPTION("API Driver for PL330 DMAC");
2824MODULE_LICENSE("GPL"); 2916MODULE_LICENSE("GPL");