diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 0e1f567..5f9b867c 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -266,9 +266,6 @@ static unsigned cmd_line;
 
 #define NR_DEFAULT_DESC	16
 
-/* Delay for runtime PM autosuspend, ms */
-#define PL330_AUTOSUSPEND_DELAY 20
-
 /* Populated by the PL330 core driver for DMA API driver's info */
 struct pl330_config {
 	u32	periph_id;
@@ -484,6 +481,8 @@ struct pl330_dmac {
 	enum pl330_dmac_state	state;
 	/* Holds list of reqs with due callbacks */
 	struct list_head        req_done;
+	/* Refcount for AMBA clock management */
+	unsigned int		pclk_refcnt;
 
 	/* Peripheral channels connected to this DMAC */
 	unsigned int num_peripherals;
@@ -548,6 +547,30 @@ static inline u32 get_revision(u32 periph_id)
 	return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
 }
 
+static inline int pl330_pclk_enable(struct pl330_dmac *pl330)
+{
+	struct amba_device *pcdev = to_amba_device(pl330->ddma.dev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&pl330->lock, flags);
+	ret = pl330->pclk_refcnt++ ? 0 : amba_pclk_enable(pcdev);
+	spin_unlock_irqrestore(&pl330->lock, flags);
+
+	return ret;
+}
+
+static inline void pl330_pclk_disable(struct pl330_dmac *pl330)
+{
+	struct amba_device *pcdev = to_amba_device(pl330->ddma.dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pl330->lock, flags);
+	if (--pl330->pclk_refcnt == 0)
+		amba_pclk_disable(pcdev);
+	spin_unlock_irqrestore(&pl330->lock, flags);
+}
+
 static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
 		enum pl330_dst da, u16 val)
 {
@@ -2032,11 +2055,9 @@ static void pl330_tasklet(unsigned long data)
 	}
 	spin_unlock_irqrestore(&pch->lock, flags);
 
-	/* If work list empty, power down */
-	if (power_down) {
-		pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
-		pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
-	}
+	/* If work list empty, disable clock */
+	if (power_down)
+		pl330_pclk_disable(pch->dmac);
 }
 
 bool pl330_filter(struct dma_chan *chan, void *param)
@@ -2155,6 +2176,21 @@ static int pl330_terminate_all(struct dma_chan *chan)
 	return 0;
 }
 
+static int pl330_pm_get(struct dma_chan *chan)
+{
+	struct dma_pl330_chan *pch = to_pchan(chan);
+
+	return pm_runtime_get_sync(pch->dmac->ddma.dev);
+}
+
+static int pl330_pm_put(struct dma_chan *chan)
+{
+	struct dma_pl330_chan *pch = to_pchan(chan);
+
+	pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
+	return pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
+}
+
 /*
  * We don't support DMA_RESUME command because of hardware
  * limitations, so after pausing the channel we cannot restore
@@ -2167,8 +2203,12 @@ int pl330_pause(struct dma_chan *chan)
 	struct dma_pl330_chan *pch = to_pchan(chan);
 	struct pl330_dmac *pl330 = pch->dmac;
 	unsigned long flags;
+	int ret;
+
+	ret = pl330_pclk_enable(pl330);
+	if (ret < 0)
+		return ret;
 
-	pm_runtime_get_sync(pl330->ddma.dev);
 	spin_lock_irqsave(&pch->lock, flags);
 
 	spin_lock(&pl330->lock);
@@ -2176,8 +2216,7 @@ int pl330_pause(struct dma_chan *chan)
 	spin_unlock(&pl330->lock);
 
 	spin_unlock_irqrestore(&pch->lock, flags);
-	pm_runtime_mark_last_busy(pl330->ddma.dev);
-	pm_runtime_put_autosuspend(pl330->ddma.dev);
+	pl330_pclk_disable(pl330);
 
 	return 0;
 }
@@ -2186,10 +2225,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
 	unsigned long flags;
+	int ret;
 
 	tasklet_kill(&pch->task);
 
 	pm_runtime_get_sync(pch->dmac->ddma.dev);
+	ret = pl330_pclk_enable(pch->dmac);
+	if (ret < 0)
+		return;
+
 	spin_lock_irqsave(&pch->lock, flags);
 
 	pl330_release_channel(pch->thread);
@@ -2199,6 +2243,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
 		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
 
 	spin_unlock_irqrestore(&pch->lock, flags);
+	pl330_pclk_disable(pch->dmac);
 	pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
 	pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
 }
@@ -2207,11 +2252,14 @@ int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
 		struct dma_pl330_desc *desc)
 {
 	struct pl330_thread *thrd = pch->thread;
-	struct pl330_dmac *pl330 = pch->dmac;
 	void __iomem *regs = thrd->dmac->base;
 	u32 val, addr;
+	int ret;
+
+	ret = pl330_pclk_enable(pch->dmac);
+	if (ret < 0)
+		return ret;
 
-	pm_runtime_get_sync(pl330->ddma.dev);
 	val = addr = 0;
 	if (desc->rqcfg.src_inc) {
 		val = readl(regs + SA(thrd->id));
@@ -2220,8 +2268,8 @@ int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
 		val = readl(regs + DA(thrd->id));
 		addr = desc->px.dst_addr;
 	}
-	pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
-	pm_runtime_put_autosuspend(pl330->ddma.dev);
+
+	pl330_pclk_disable(pch->dmac);
 	return val - addr;
 }
 
@@ -2277,16 +2325,19 @@ static void pl330_issue_pending(struct dma_chan *chan)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
 	unsigned long flags;
+	int ret;
 
 	spin_lock_irqsave(&pch->lock, flags);
 	if (list_empty(&pch->work_list)) {
 		/*
 		 * Warn on nothing pending. Empty submitted_list may
-		 * break our pm_runtime usage counter as it is
-		 * updated on work_list emptiness status.
+		 * break our clock usage counter as it is updated on
+		 * work_list emptiness status.
 		 */
 		WARN_ON(list_empty(&pch->submitted_list));
-		pm_runtime_get_sync(pch->dmac->ddma.dev);
+		ret = pl330_pclk_enable(pch->dmac);
+		if (ret < 0)
+			return;
 	}
 	list_splice_tail_init(&pch->submitted_list, &pch->work_list);
 	spin_unlock_irqrestore(&pch->lock, flags);
@@ -2720,13 +2771,13 @@ static irqreturn_t pl330_irq_handler(int irq, void *data)
 static int __maybe_unused pl330_suspend(struct device *dev)
 {
 	struct amba_device *pcdev = to_amba_device(dev);
+	struct pl330_dmac *pl330 = amba_get_drvdata(pcdev);
 
 	pm_runtime_disable(dev);
 
-	if (!pm_runtime_status_suspended(dev)) {
-		/* amba did not disable the clock */
+	if (pl330->pclk_refcnt)
 		amba_pclk_disable(pcdev);
-	}
+
 	amba_pclk_unprepare(pcdev);
 
 	return 0;
@@ -2735,14 +2786,18 @@ static int __maybe_unused pl330_suspend(struct device *dev)
 static int __maybe_unused pl330_resume(struct device *dev)
 {
 	struct amba_device *pcdev = to_amba_device(dev);
+	struct pl330_dmac *pl330 = amba_get_drvdata(pcdev);
 	int ret;
 
 	ret = amba_pclk_prepare(pcdev);
 	if (ret)
 		return ret;
 
-	if (!pm_runtime_status_suspended(dev))
+	if (pl330->pclk_refcnt) {
 		ret = amba_pclk_enable(pcdev);
+		if (ret)
+			return ret;
+	}
 
 	pm_runtime_enable(dev);
 
@@ -2815,6 +2870,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
 		dev_warn(&adev->dev, "unable to allocate desc\n");
 
+	amba_pclk_disable(adev);
+
 	INIT_LIST_HEAD(&pd->channels);
 
 	/* Initialize channel parameters */
@@ -2869,6 +2926,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	pd->device_tx_status = pl330_tx_status;
 	pd->device_prep_slave_sg = pl330_prep_slave_sg;
 	pd->device_config = pl330_config;
+	pd->device_pm_get = pl330_pm_get;
+	pd->device_pm_put = pl330_pm_put;
 	pd->device_pause = pl330_pause;
 	pd->device_terminate_all = pl330_terminate_all;
 	pd->device_issue_pending = pl330_issue_pending;
@@ -2902,7 +2961,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	if (ret)
 		dev_err(&adev->dev, "unable to set the seg size\n");
 
-
 	dev_info(&adev->dev,
 		"Loaded driver for PL330 DMAC-%x\n", adev->periphid);
 	dev_info(&adev->dev,
@@ -2910,9 +2968,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan,
 		pcfg->num_peri, pcfg->num_events);
 
-	pm_runtime_irq_safe(&adev->dev);
 	pm_runtime_use_autosuspend(&adev->dev);
-	pm_runtime_set_autosuspend_delay(&adev->dev, PL330_AUTOSUSPEND_DELAY);
 	pm_runtime_mark_last_busy(&adev->dev);
 	pm_runtime_put_autosuspend(&adev->dev);
 
@@ -2987,6 +3043,7 @@ static struct amba_driver pl330_driver = {
 	.id_table = pl330_ids,
 	.probe = pl330_probe,
 	.remove = pl330_remove,
+	.no_pm_pclk_management = true,
 };
 
 module_amba_driver(pl330_driver);
