Merge branch 'topic/imx' into for-linus
[linux-2.6-block.git] / drivers / dma / imx-sdma.c
index af14a8d6efa8855d36cc9a727064f1f3919495eb..88197d5ac3b97cb3463cd681d2c8b8d756df4741 100644 (file)
@@ -441,6 +441,8 @@ struct sdma_engine {
        unsigned int                    irq;
        dma_addr_t                      bd0_phys;
        struct sdma_buffer_descriptor   *bd0;
+       /* clock ratio for AHB:SDMA core. 1:1 is 1, 2:1 is 0*/
+       bool                            clk_ratio;
 };
 
 static int sdma_config_write(struct dma_chan *chan,
@@ -663,8 +665,11 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
                dev_err(sdma->dev, "Timeout waiting for CH0 ready\n");
 
        /* Set bits of CONFIG register with dynamic context switching */
-       if (readl(sdma->regs + SDMA_H_CONFIG) == 0)
-               writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
+       reg = readl(sdma->regs + SDMA_H_CONFIG);
+       if ((reg & SDMA_H_CONFIG_CSM) == 0) {
+               reg |= SDMA_H_CONFIG_CSM;
+               writel_relaxed(reg, sdma->regs + SDMA_H_CONFIG);
+       }
 
        return ret;
 }
@@ -1847,6 +1852,9 @@ static int sdma_init(struct sdma_engine *sdma)
        if (ret)
                goto disable_clk_ipg;
 
+       if (clk_get_rate(sdma->clk_ahb) == clk_get_rate(sdma->clk_ipg))
+               sdma->clk_ratio = 1;
+
        /* Be sure SDMA has not started yet */
        writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
 
@@ -1887,8 +1895,10 @@ static int sdma_init(struct sdma_engine *sdma)
        writel_relaxed(0x4050, sdma->regs + SDMA_CHN0ADDR);
 
        /* Set bits of CONFIG register but with static context switching */
-       /* FIXME: Check whether to set ACR bit depending on clock ratios */
-       writel_relaxed(0, sdma->regs + SDMA_H_CONFIG);
+       if (sdma->clk_ratio)
+               writel_relaxed(SDMA_H_CONFIG_ACR, sdma->regs + SDMA_H_CONFIG);
+       else
+               writel_relaxed(0, sdma->regs + SDMA_H_CONFIG);
 
        writel_relaxed(ccb_phys, sdma->regs + SDMA_H_C0PTR);
 
@@ -1911,11 +1921,16 @@ disable_clk_ipg:
 static bool sdma_filter_fn(struct dma_chan *chan, void *fn_param)
 {
        struct sdma_channel *sdmac = to_sdma_chan(chan);
+       struct sdma_engine *sdma = sdmac->sdma;
        struct imx_dma_data *data = fn_param;
 
        if (!imx_dma_is_general_purpose(chan))
                return false;
 
+       /* return false if it's not the right device */
+       if (sdma->dev->of_node != data->of_node)
+               return false;
+
        sdmac->data = *data;
        chan->private = &sdmac->data;
 
@@ -1943,6 +1958,7 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
         * be set to sdmac->event_id1.
         */
        data.dma_request2 = 0;
+       data.of_node = ofdma->of_node;
 
        return dma_request_channel(mask, sdma_filter_fn, &data);
 }
@@ -2105,6 +2121,7 @@ static int sdma_probe(struct platform_device *pdev)
        sdma->dma_device.device_prep_dma_memcpy = sdma_prep_memcpy;
        sdma->dma_device.device_issue_pending = sdma_issue_pending;
        sdma->dma_device.dev->dma_parms = &sdma->dma_parms;
+       sdma->dma_device.copy_align = 2;
        dma_set_max_seg_size(sdma->dma_device.dev, SDMA_BD_MAX_CNT);
 
        platform_set_drvdata(pdev, sdma);