}
#ifndef CONFIG_SYS_DCACHE_OFF
-void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
+static void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
{
uint32_t addr;
uint32_t size;
flush_dcache_range(addr, addr + size);
}
#else
-inline void mxs_dma_flush_desc(struct mxs_dma_desc *desc) {}
+static inline void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
+{
+}
#endif
/*
static int mxs_dma_reset(int channel)
{
int ret;
-#if defined(CONFIG_MX23)
+#if defined(CONFIG_SOC_MX23)
uint32_t *setreg = &apbh_regs->hw_apbh_ctrl0_set;
uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
-#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6))
+#elif (defined(CONFIG_SOC_MX28) || defined(CONFIG_SOC_MX6))
uint32_t *setreg = &apbh_regs->hw_apbh_channel_ctrl_set;
uint32_t offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
#endif
pchan->flags |= MXS_DMA_FLAGS_ALLOCATED;
pchan->active_num = 0;
pchan->pending_num = 0;
+ pchan->timeout = 10000000;
INIT_LIST_HEAD(&pchan->active);
INIT_LIST_HEAD(&pchan->done);
return 0;
}
+/*
+ * Set the timeout for any DMA operation started with mxs_dma_go()
+ * The timeout value given is in milliseconds
+ */
+int mxs_dma_set_timeout(int channel, unsigned long timeout)
+{
+ int ret;
+ struct mxs_dma_chan *pchan;
+
+ ret = mxs_dma_validate_chan(channel);
+ if (ret)
+ return ret;
+
+ pchan = &mxs_dma_channels[channel];
+
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY)
+ return -EBUSY;
+
+ if (timeout > ~0UL / 1000)
+ return -EINVAL;
+
+ pchan->timeout = timeout;
+ return 0;
+}
+
+unsigned long mxs_dma_get_timeout(int channel)
+{
+ int ret;
+ struct mxs_dma_chan *pchan;
+
+ ret = mxs_dma_validate_chan(channel);
+ if (ret)
+ return 0;
+
+ pchan = &mxs_dma_channels[channel];
+ return pchan->timeout;
+}
+
/*
* Allocate DMA descriptor
*/
*/
int mxs_dma_go(int chan)
{
- uint32_t timeout = 10000;
int ret;
-
+ struct mxs_dma_chan *pchan;
LIST_HEAD(tmp_desc_list);
+ ret = mxs_dma_validate_chan(chan);
+ if (ret)
+ return ret;
+
+ pchan = &mxs_dma_channels[chan];
+
mxs_dma_enable_irq(chan, 1);
- mxs_dma_enable(chan);
+ ret = mxs_dma_enable(chan);
+ if (ret) {
+ mxs_dma_enable_irq(chan, 0);
+ return ret;
+ }
/* Wait for DMA to finish. */
- ret = mxs_dma_wait_complete(timeout, chan);
+ ret = mxs_dma_wait_complete(pchan->timeout * 1000, chan);
/* Clear out the descriptors we just ran. */
mxs_dma_finish(chan, &tmp_desc_list);
return ret;
}
+/*
+ * Execute a continuously running circular DMA descriptor.
+ * NOTE: This is not intended for general use, but rather
+ * for the LCD driver in Smart-LCD mode. It allows
+ * continuous triggering of the RUN bit there.
+ */
+void mxs_dma_circ_start(int chan, struct mxs_dma_desc *pdesc)
+{
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
+
+ mxs_dma_flush_desc(pdesc);
+
+ mxs_dma_enable_irq(chan, 1);
+
+ writel(mxs_dma_cmd_address(pdesc),
+ &apbh_regs->ch[chan].hw_apbh_ch_nxtcmdar);
+ writel(1, &apbh_regs->ch[chan].hw_apbh_ch_sema);
+ writel(1 << (chan + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
+ &apbh_regs->hw_apbh_ctrl0_clr);
+}
+
/*
* Initialize the DMA hardware
*/