|
@@ -16,6 +16,7 @@
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/io.h>
|
|
|
+#include <linux/iopoll.h>
|
|
|
#include <linux/sizes.h>
|
|
|
#include <linux/pm_runtime.h>
|
|
|
|
|
@@ -184,6 +185,24 @@ static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
|
|
|
acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
|
|
|
}
|
|
|
|
|
|
+static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num)
|
|
|
+{
|
|
|
+ u32 dma_ctrl;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /* clear the reset bit */
|
|
|
+ dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
|
|
|
+ dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK;
|
|
|
+ acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
|
|
|
+ /* check the reset bit before programming configuration registers */
|
|
|
+ ret = readl_poll_timeout(acp_mmio + ((mmACP_DMA_CNTL_0 + ch_num) * 4),
|
|
|
+ dma_ctrl,
|
|
|
+ !(dma_ctrl & ACP_DMA_CNTL_0__DMAChRst_MASK),
|
|
|
+ 100, ACP_DMA_RESET_TIME);
|
|
|
+ if (ret < 0)
|
|
|
+ pr_err("Failed to clear reset of channel : %d\n", ch_num);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Initialize the DMA descriptor information for transfer between
|
|
|
* system memory <-> ACP SRAM
|
|
@@ -236,6 +255,7 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
|
|
|
config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
|
|
|
&dmadscr[i]);
|
|
|
}
|
|
|
+ pre_config_reset(acp_mmio, ch);
|
|
|
config_acp_dma_channel(acp_mmio, ch,
|
|
|
dma_dscr_idx - 1,
|
|
|
NUM_DSCRS_PER_CHANNEL,
|
|
@@ -275,6 +295,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
|
|
|
config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
|
|
|
&dmadscr[i]);
|
|
|
}
|
|
|
+ pre_config_reset(acp_mmio, ch);
|
|
|
/* Configure the DMA channel with the above descriptore */
|
|
|
config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
|
|
|
NUM_DSCRS_PER_CHANNEL,
|