*/
static int mxs_dma_read_semaphore(int channel)
{
- struct mx28_apbh_regs *apbh_regs =
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
uint32_t tmp;
int ret;
return tmp;
}
+#ifndef CONFIG_SYS_DCACHE_OFF
+void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
+{
+ uint32_t addr;
+ uint32_t size;
+
+ addr = (uint32_t)desc;
+ size = roundup(sizeof(struct mxs_dma_desc), MXS_DMA_ALIGNMENT);
+
+ flush_dcache_range(addr, addr + size);
+}
+#else
+inline void mxs_dma_flush_desc(struct mxs_dma_desc *desc) {}
+#endif
+
/*
* Enable a DMA channel.
*
*/
static int mxs_dma_enable(int channel)
{
- struct mx28_apbh_regs *apbh_regs =
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
unsigned int sem;
struct mxs_dma_chan *pchan;
struct mxs_dma_desc *pdesc;
static int mxs_dma_disable(int channel)
{
struct mxs_dma_chan *pchan;
- struct mx28_apbh_regs *apbh_regs =
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
*/
static int mxs_dma_reset(int channel)
{
- struct mx28_apbh_regs *apbh_regs =
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
+#if defined(CONFIG_MX23)
+ uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_ctrl0_set);
+ uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
+#elif defined(CONFIG_MX28)
+ uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_channel_ctrl_set);
+ uint32_t offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
+#endif
ret = mxs_dma_validate_chan(channel);
if (ret)
return ret;
- writel(1 << (channel + APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET),
- &apbh_regs->hw_apbh_channel_ctrl_set);
+ writel(1 << (channel + offset), setreg);
return 0;
}
*/
static int mxs_dma_enable_irq(int channel, int enable)
{
- struct mx28_apbh_regs *apbh_regs =
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
*/
static int mxs_dma_ack_irq(int channel)
{
- struct mx28_apbh_regs *apbh_regs =
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
* The channel will NOT be released if it's marked "busy" (see
* mxs_dma_enable()).
*/
-static int mxs_dma_release(int channel)
+int mxs_dma_release(int channel)
{
struct mxs_dma_chan *pchan;
int ret;
struct mxs_dma_desc *mxs_dma_desc_alloc(void)
{
struct mxs_dma_desc *pdesc;
+ uint32_t size;
- pdesc = memalign(MXS_DMA_ALIGNMENT, sizeof(struct mxs_dma_desc));
+ size = roundup(sizeof(struct mxs_dma_desc), MXS_DMA_ALIGNMENT);
+ pdesc = memalign(MXS_DMA_ALIGNMENT, size);
if (pdesc == NULL)
return NULL;
last->cmd.next = mxs_dma_cmd_address(pdesc);
last->cmd.data |= MXS_DMA_DESC_CHAIN;
+
+ mxs_dma_flush_desc(last);
}
pdesc->flags |= MXS_DMA_DESC_READY;
if (pdesc->flags & MXS_DMA_DESC_FIRST)
pchan->pending_num++;
list_add_tail(&pdesc->node, &pchan->active);
+ mxs_dma_flush_desc(pdesc);
+
return ret;
}
*/
static int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
{
- struct mx28_apbh_regs *apbh_regs =
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(chan);
if (ret)
return ret;
- if (mx28_wait_mask_set(&apbh_regs->hw_apbh_ctrl1_reg,
+ if (mxs_wait_mask_set(&apbh_regs->hw_apbh_ctrl1_reg,
1 << chan, timeout)) {
ret = -ETIMEDOUT;
mxs_dma_reset(chan);
*/
int mxs_dma_go(int chan)
{
- uint32_t timeout = 10000;
+ uint32_t timeout = 10000000;
int ret;
LIST_HEAD(tmp_desc_list);
/*
* Initialize the DMA hardware
*/
-int mxs_dma_init(void)
+void mxs_dma_init(void)
{
- struct mx28_apbh_regs *apbh_regs =
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
- struct mxs_dma_chan *pchan;
- int ret, channel;
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
- mx28_reset_block(&apbh_regs->hw_apbh_ctrl0_reg);
+ mxs_reset_block(&apbh_regs->hw_apbh_ctrl0_reg);
#ifdef CONFIG_APBH_DMA_BURST8
writel(APBH_CTRL0_AHB_BURST8_EN,
writel(APBH_CTRL0_APB_BURST_EN,
&apbh_regs->hw_apbh_ctrl0_clr);
#endif
+}
- for (channel = 0; channel < MXS_MAX_DMA_CHANNELS; channel++) {
- pchan = mxs_dma_channels + channel;
- pchan->flags = MXS_DMA_FLAGS_VALID;
+int mxs_dma_init_channel(int channel)
+{
+ struct mxs_dma_chan *pchan;
+ int ret;
- ret = mxs_dma_request(channel);
+ pchan = mxs_dma_channels + channel;
+ pchan->flags = MXS_DMA_FLAGS_VALID;
- if (ret) {
- printf("MXS DMA: Can't acquire DMA channel %i\n",
- channel);
+ ret = mxs_dma_request(channel);
- goto err;
- }
-
- mxs_dma_reset(channel);
- mxs_dma_ack_irq(channel);
+ if (ret) {
+ printf("MXS DMA: Can't acquire DMA channel %i\n",
+ channel);
+ return ret;
}
- return 0;
+ mxs_dma_reset(channel);
+ mxs_dma_ack_irq(channel);
-err:
- while (--channel >= 0)
- mxs_dma_release(channel);
- return ret;
+ return 0;
}