]> git.sur5r.net Git - u-boot/commitdiff
DMA: Split the APBH DMA init into block and channel init
authorMarek Vasut <marex@denx.de>
Sun, 8 Apr 2012 17:34:46 +0000 (17:34 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Mon, 16 Apr 2012 12:53:59 +0000 (14:53 +0200)
This fixes the issue where mxs_dma_init() was called either twice or never,
without introducing any new init hooks.

The idea is to allow each and every device using the APBH DMA block to
configure and request only the channels it uses, instead of making it call init
for all the channels as is now.

The common DMA block init part, which only configures the block, is then called
from CPUs arch_cpu_init() call.

NOTE: This patch depends on:

http://patchwork.ozlabs.org/patch/150957/

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Tested-by: Fabio Estevam <fabio.estevam@freescale.com>
arch/arm/cpu/arm926ejs/mx28/mx28.c
arch/arm/include/asm/arch-mx28/dma.h
drivers/dma/apbh_dma.c
drivers/mmc/mxsmmc.c
drivers/mtd/nand/mxs_nand.c

index cf6d4e9bd46aa9260e85ee040992b03dc5ceb49c..dc0338dfb585699bcc0850f28c19c77fdf9a8f1a 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/dma.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/iomux.h>
 #include <asm/arch/imx-regs.h>
@@ -172,6 +173,11 @@ int arch_cpu_init(void)
         */
        mxs_gpio_init();
 
+#ifdef CONFIG_APBH_DMA
+       /* Start APBH DMA */
+       mxs_dma_init();
+#endif
+
        return 0;
 }
 #endif
index 52747e2fbf4caed84f2a0b4c7cdb8ac92cb1fcdc..4a1820bdee3244b04f4f3cf375e065ac55f24a65 100644 (file)
@@ -140,6 +140,8 @@ void mxs_dma_desc_free(struct mxs_dma_desc *);
 int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc);
 
 int mxs_dma_go(int chan);
-int mxs_dma_init(void);
+void mxs_dma_init(void);
+int mxs_dma_init_channel(int chan);
+int mxs_dma_release(int chan);
 
 #endif /* __DMA_H__ */
index c086629b0a91e967b1cd078b52af48122665de5c..cb2193ec558368ac9c189341775b2a11e76a166e 100644 (file)
@@ -316,7 +316,7 @@ static int mxs_dma_request(int 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;
@@ -552,12 +552,10 @@ int mxs_dma_go(int chan)
 /*
  * 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;
 
        mx28_reset_block(&apbh_regs->hw_apbh_ctrl0_reg);
 
@@ -576,28 +574,26 @@ int mxs_dma_init(void)
        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;
-
-               ret = mxs_dma_request(channel);
+int mxs_dma_init_channel(int channel)
+{
+       struct mxs_dma_chan *pchan;
+       int ret;
 
-               if (ret) {
-                       printf("MXS DMA: Can't acquire DMA channel %i\n",
-                               channel);
+       pchan = mxs_dma_channels + channel;
+       pchan->flags = MXS_DMA_FLAGS_VALID;
 
-                       goto err;
-               }
+       ret = mxs_dma_request(channel);
 
-               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;
 }
index dfceaef953a918aa38eff4136318c036a7a97426..35c6bdabb06d4b71e8cf46263aa22c2cbf0301ec 100644 (file)
@@ -338,6 +338,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))
                (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
        struct mmc *mmc = NULL;
        struct mxsmmc_priv *priv = NULL;
+       int ret;
 
        mmc = malloc(sizeof(struct mmc));
        if (!mmc)
@@ -356,6 +357,10 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))
                return -ENOMEM;
        }
 
+       ret = mxs_dma_init_channel(id);
+       if (ret)
+               return ret;
+
        priv->mmc_is_wp = wp;
        priv->id = id;
        switch (id) {
index 4b1297a2fdc140bf46b9ece19c5f611b5578b98b..9c9581105414fae8a2dc53f38a6dd5585446a838 100644 (file)
@@ -1058,7 +1058,7 @@ int mxs_nand_init(struct mxs_nand_info *info)
 {
        struct mx28_gpmi_regs *gpmi_regs =
                (struct mx28_gpmi_regs *)MXS_GPMI_BASE;
-       int i = 0;
+       int i = 0, j;
 
        info->desc = malloc(sizeof(struct mxs_dma_desc *) *
                                MXS_NAND_DMA_DESCRIPTOR_COUNT);
@@ -1073,7 +1073,11 @@ int mxs_nand_init(struct mxs_nand_info *info)
        }
 
        /* Init the DMA controller. */
-       mxs_dma_init();
+       for (j = MXS_DMA_CHANNEL_AHB_APBH_GPMI0;
+               j <= MXS_DMA_CHANNEL_AHB_APBH_GPMI7; j++) {
+               if (mxs_dma_init_channel(j))
+                       goto err3;
+       }
 
        /* Reset the GPMI block. */
        mx28_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
@@ -1089,6 +1093,9 @@ int mxs_nand_init(struct mxs_nand_info *info)
 
        return 0;
 
+err3:
+       for (--j; j >= 0; j--)
+               mxs_dma_release(j);
 err2:
        free(info->desc);
 err1: