#define SDMA_H_CONFIG_ACR BIT(4) /* indicates if AHB freq /core freq = 2 or 1 */
#define SDMA_H_CONFIG_CSM (3) /* indicates which context switch mode is selected*/
+static void sdma_pm_clk_enable(struct sdma_engine *sdma, bool direct, bool enable)
+{
+ if (enable) {
+ if (sdma->drvdata->pm_runtime)
+ pm_runtime_get_sync(sdma->dev);
+ else {
+ clk_enable(sdma->clk_ipg);
+ clk_enable(sdma->clk_ahb);
+ }
+ } else {
+ if (sdma->drvdata->pm_runtime) {
+ if (direct) {
+ pm_runtime_put_sync_suspend(sdma->dev);
+ } else {
+ pm_runtime_mark_last_busy(sdma->dev);
+ pm_runtime_put_autosuspend(sdma->dev);
+ }
+ } else {
+ clk_disable(sdma->clk_ipg);
+ clk_disable(sdma->clk_ahb);
+ }
+ }
+}
+
static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
{
u32 chnenbl0 = sdma->drvdata->chnenbl0;
struct sdma_engine *sdma = dev_id;
unsigned long stat;
- if (sdma->drvdata->pm_runtime)
- pm_runtime_get_sync(sdma->dev);
- else {
- clk_enable(sdma->clk_ipg);
- clk_enable(sdma->clk_ahb);
- }
-
+ sdma_pm_clk_enable(sdma, false, true);
stat = readl_relaxed(sdma->regs + SDMA_H_INTR);
writel_relaxed(stat, sdma->regs + SDMA_H_INTR);
/* channel 0 is special and not handled here, see run_channel0() */
__clear_bit(channel, &stat);
}
- if (sdma->drvdata->pm_runtime) {
- pm_runtime_mark_last_busy(sdma->dev);
- pm_runtime_put_autosuspend(sdma->dev);
- } else {
- clk_disable(sdma->clk_ipg);
- clk_disable(sdma->clk_ahb);
- }
+ sdma_pm_clk_enable(sdma, false, false);
return IRQ_HANDLED;
}
struct sdma_channel *sdmac = to_sdma_chan(chan);
unsigned long flags;
- if (sdmac->sdma->drvdata->pm_runtime)
- pm_runtime_get_sync(sdmac->sdma->dev);
-
+ sdma_pm_clk_enable(sdmac->sdma, false, true);
spin_lock_irqsave(&sdmac->vc.lock, flags);
sdma_disable_channel(chan);
spin_unlock_irqrestore(&sdmac->vc.lock, flags);
- if (sdmac->sdma->drvdata->pm_runtime) {
- pm_runtime_mark_last_busy(sdmac->sdma->dev);
- pm_runtime_put_autosuspend(sdmac->sdma->dev);
- }
+ sdma_pm_clk_enable(sdmac->sdma, false, false);
return 0;
}
if (unlikely(!sdmac->sdma->fw_data))
return;
- if (sdmac->sdma->drvdata->pm_runtime)
- pm_runtime_get_sync(sdmac->sdma->dev);
-
+ sdma_pm_clk_enable(sdmac->sdma, false, true);
sdma_terminate_all(chan);
sdma_channel_synchronize(chan);
kfree(sdmac->audio_config);
sdmac->audio_config = NULL;
-
- if (sdmac->sdma->drvdata->pm_runtime) {
- pm_runtime_mark_last_busy(sdmac->sdma->dev);
- pm_runtime_put_autosuspend(sdmac->sdma->dev);
- }
+ sdma_pm_clk_enable(sdmac->sdma, false, false);
}
static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
dev_dbg(sdma->dev, "memcpy: %pad->%pad, len=%zu, channel=%d.\n",
&dma_src, &dma_dst, len, channel);
- if (sdma->drvdata->pm_runtime)
- pm_runtime_get_sync(sdmac->sdma->dev);
-
+ sdma_pm_clk_enable(sdmac->sdma, false, true);
desc = sdma_transfer_init(sdmac, DMA_MEM_TO_MEM,
len / SDMA_BD_MAX_CNT + 1);
if (!desc) {
- if (sdma->drvdata->pm_runtime)
- pm_runtime_put_sync_suspend(sdmac->sdma->dev);
+ sdma_pm_clk_enable(sdmac->sdma, true, false);
return NULL;
}
bd->mode.status = param;
} while (len);
- if (sdmac->sdma->drvdata->pm_runtime) {
- pm_runtime_mark_last_busy(sdmac->sdma->dev);
- pm_runtime_put_autosuspend(sdmac->sdma->dev);
- }
+ sdma_pm_clk_enable(sdmac->sdma, false, false);
return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
}
struct scatterlist *sg;
struct sdma_desc *desc;
- if (sdma->drvdata->pm_runtime)
- pm_runtime_get_sync(sdmac->sdma->dev);
-
+ sdma_pm_clk_enable(sdmac->sdma, false, true);
sdma_config_write(chan, &sdmac->slave_config, direction);
desc = sdma_transfer_init(sdmac, direction, sg_len);
bd->mode.status = param;
}
- if (sdmac->sdma->drvdata->pm_runtime) {
- pm_runtime_mark_last_busy(sdmac->sdma->dev);
- pm_runtime_put_autosuspend(sdmac->sdma->dev);
- }
+ sdma_pm_clk_enable(sdmac->sdma, false, false);
return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
err_bd_out:
kfree(desc);
err_out:
sdmac->status = DMA_ERROR;
- if (sdma->drvdata->pm_runtime)
- pm_runtime_put_sync_suspend(sdmac->sdma->dev);
+ sdma_pm_clk_enable(sdmac->sdma, true, false);
+
return NULL;
}
dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
- if (sdma->drvdata->pm_runtime)
- pm_runtime_get_sync(sdmac->sdma->dev);
+ sdma_pm_clk_enable(sdmac->sdma, false, true);
if (sdmac->peripheral_type != IMX_DMATYPE_HDMI)
num_periods = buf_len / period_len;
i++;
}
- if (sdmac->sdma->drvdata->pm_runtime) {
- pm_runtime_mark_last_busy(sdmac->sdma->dev);
- pm_runtime_put_autosuspend(sdmac->sdma->dev);
- }
+ sdma_pm_clk_enable(sdmac->sdma, false, false);
return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
err_bd_out:
kfree(desc);
err_out:
sdmac->status = DMA_ERROR;
- if (sdma->drvdata->pm_runtime)
- pm_runtime_put_sync_suspend(sdmac->sdma->dev);
+ sdma_pm_clk_enable(sdmac->sdma, true, false);
+
return NULL;
}
struct sdma_channel *sdmac = to_sdma_chan(chan);
unsigned long flags;
- if (sdmac->sdma->drvdata->pm_runtime)
- pm_runtime_get_sync(sdmac->sdma->dev);
-
+ sdma_pm_clk_enable(sdmac->sdma, false, true);
spin_lock_irqsave(&sdmac->vc.lock, flags);
if (vchan_issue_pending(&sdmac->vc) && !sdmac->desc)
sdma_start_desc(sdmac);
spin_unlock_irqrestore(&sdmac->vc.lock, flags);
- if (sdmac->sdma->drvdata->pm_runtime) {
- pm_runtime_mark_last_busy(sdmac->sdma->dev);
- pm_runtime_put_autosuspend(sdmac->sdma->dev);
- }
+ sdma_pm_clk_enable(sdmac->sdma, false, false);
}
static void sdma_load_firmware(const struct firmware *fw, void *context)