This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem in DMA transfer after enabling the I-Cache & D-Cache

Other Parts Discussed in Thread: SYSCONFIG

Hi,

I'm  working on omap5 based customized  processor. I'm having latest u-boot souce code.

I have enabled the DMA in eMMC driver. without enabling the I-cache & D-cache this setup was working fine.

When I enabled the I-Cache & D-Cache in u-boot with DMA,  I'm getting error. Without DMA I don't have any problem.

I  want to enable the both DMA & Caches.

how can I do this.

Kindly help me out to resolve this issue.

Thanks

ramappa

  • Ramappa,

    have you tried with the latest TI SDK U-boot release for that processor? Which U-boot version do you actually use and where did you get it from?

    Although I can't reproduce this atm., I's suppose this is a cache choerency issue. Have you checked doc/README.arm-caches in the U-boot sources?


    Regards,
    Marc

  • Hi Marc,

    I'm using the latest u-boot source code.

    I have added DMA support for MMC READ in it.

    I have enabled the I-Cache & D-Cache with DMA in u-boot.

    After going through the doc/README.arm-caches.

    To achieve cache coherency,  before starting DMA I'm invalidating the cache as follows.

    here 'buf' is DMA buffer.

    start = buf;
    end = start + (blkSiz * numBlk);

     /* Invalidating the DMA Buffer in D-Cache */
     invalidate_dcache_range(start, end);


    But I'm getting the following ERROR.

    ERROR: v7_dcache_inval_range - start address is not aligned - 0xdeefb310                                              
    ERROR: v7_dcache_inval_range - stop address is not aligned - 0xdeeff710

     

    Kindly help me to resolve this issue.

     

     

    Thanks

    Ramappa

  • Ramappa,

    we typically support U-boot versions that come with the respective SDK. I strongly suggest doing your tests in the U-boot version coming with the latest GLSDK release.

    The error shows up upon invalidating buffers that are not properly aligned from cache perspective. Try to allocate a buffer that is aligned w/ cache lines.

    Additionally, please give references to the files you have changed, including the respective line numbers.

    Regards,
    Marc

  • Hi Marc,

    Give me your mail ID.

    you can send your mail ID to hugar.ram@gmail.com

    Thanks

    Ramappa

  • Ramappa,

    for such issues e2e is the preferred way as other users can participate.

    Let's focus on this topic in the thread you opened for your work on the OMAP5 EVM at http://e2e.ti.com/support/omap/f/885/p/314829/1101180.aspx and stop this one.

    Regards,
    Marc

  • Hi Marc,

    I understand,  e2e is public forum.  Sorry for that.


    As I'm working in client place, I don't have permissions to post code directly in to public forum.

    After showing your mail, I got permission to share that.

    DON'T MISTAKE.....!!!!!!!!!

    I'm sharing the code as follows.

    In the file "driver/mmc/omap_hsmmc.c"

    402 #ifdef CONFIG_OMAP_MMC_USE_DMA_READ
    403                 if (data->flags & MMC_DATA_READ) {
    404
    405                         if ((((unsigned)data->dest) & 3) || (((unsigned)data->blocksize) & 3)) {
    406                                 canUseDma = 0;
    407                         } else {
    408                                 flags = (flags &~ DE_DISABLE) | DE_ENABLE;
    409
    410                                 mmc_dma_start(mmc, mmc_base, data->dest,
    411                                                 data->blocksize, data->blocks, 0);
    412                         }
    413                 }
    414 #else
    415                 canUseDma = 0;
    416 #endif

    ------------------------------------------------------------------------------------------------------

    451         if (data && (data->flags & MMC_DATA_READ)) {
    452                 if(canUseDma) {
    453 #ifdef CONFIG_OMAP_MMC_USE_DMA_READ
    454                         return mmc_dma_wait_for_transfer_complete(mmc, mmc_base, data->dest,
    455                                         data->blocksize, data->blocks);
    456 #endif

    ----------------------------------------------------------------------------------------------------------------------------------------

    577 #ifdef CONFIG_OMAP_MMC_USE_DMA_READ
    578 static void mmc_dma_start(struct mmc* mmc, struct hsmmc *mmc_base, const char *buf, unsigned int blkSiz, unsigned int numBlk, int write)
    579 {
    580         static struct dma4 *dma4_cfg = (struct dma4 *)OMAP34XX_DMA4_BASE;
    581         struct dma4_chan* chan = dma4_cfg->chan + OMAP_DMA_CHANNEL_NUM;
    582         unsigned i, dmaReqNum;
    583         unsigned long csdp, ccr;
    584         unsigned long start, end;
    585         start = buf;
    586         end = start + (blkSiz * numBlk);
    587
    588         /* Invalidating the DMA Buffer in D-Cache */
    589         invalidate_dcache_range(start, end);
    590
    591         /*  figure out what our controller and dma request num are */
    592         switch (mmc - hsmmc_dev) {
    593                 default:
    594                 case 0:
    595                         dmaReqNum = write ? SDMA_REQ_MMC1_TX : SDMA_REQ_MMC1_RX;
    596                         break;
    597
    598                 case 1:
    599                         dmaReqNum = write ? SDMA_REQ_MMC2_TX : SDMA_REQ_MMC2_RX;
    600                         break;
    601
    602                 case 2:
    603                         dmaReqNum = write ? SDMA_REQ_MMC3_TX : SDMA_REQ_MMC3_RX;
    604                         break;
    605         }
    606         dmaReqNum += SDMA_REQ_NUM_OFFSET;
    607         for (i = 0; i < 4; i++) {
    608
    609                 writel(readl(&dma4_cfg->irqstatus_l[i]) | (1UL << OMAP_DMA_CHANNEL_NUM), &dma4_cfg->irqstatus_l[i]);
    610         }
    611         writel(SYSCONFIG_MIDLEMODE_NO_STBY | SYSCONFIG_SIDLEMODE_NO_IDLE | SYSCONFIG_AUTOIDLE_NONE, &dma4_cfg->ocp_sysconfig);
    612         /* configure the dma engine */
    613         csdp = CSDP_SRC_LE | CSDP_SRC_ENDIAN_LOCK | CSDP_DST_LE | CSDP_DST_ENDIAN_LOCK | CSDP_DATA_TYPE_4B;
    614         ccr = CCR_ENABLE | CCR_FIELDSYNC_FRAME | DMA_REQ_NUM_TO_CCR_VAL(dmaReqNum);
    615         if (write) {
    616                 csdp |= CSDP_WRITE_POSTED_ALL | CSDP_SRC_BURST_64B | CSDP_DST_BURST_NONE;
    617                 writel((unsigned long)buf, &chan->cssa);
    618                 writel((unsigned long)&mmc_base->data, &chan->cdsa);
    619                 ccr |= CCR_DST_SYNC | CCR_DST_AMODE_CONST_ADDR | CCR_SRC_AMODE_POSTINCR;
    620         } else {
    621
    622                 csdp |= CSDP_WRITE_POSTED_ALL_BUT_LAST | CSDP_SRC_BURST_NONE  | CSDP_DST_BURST_64B;
    623                 writel((unsigned long)&mmc_base->data, &chan->cssa);
    624                 writel((unsigned long)buf, &chan->cdsa);
    625                 ccr |= CCR_SRC_AMODE_CONST_ADDR | CCR_DST_AMODE_POSTINCR;
    626         }
    627         writel(0, &chan->ccr);
    628         writel(0, &chan->cicr);
    629         writel(0xFFFFFFFF, &chan->csr);
    630         writel(csdp, &chan->csdp);
    631         writel(blkSiz >> 2, &chan->cen);
    632         writel(numBlk, &chan->cfn);
    633         writel(CDP_TRANSFER_MODE_NORMAL, &chan->cdp);
    634         writel(ccr, &chan->ccr);
    635 }
    636
    637
    638 static int mmc_dma_wait_for_transfer_complete(struct mmc* mmc, struct hsmmc *mmc_base, const char *buf, unsigned int blkSiz, unsigned int numBlk)
    639 {
    640         static struct dma4 *dma4_cfg = (struct dma4 *)OMAP34XX_DMA4_BASE;
    641         static struct dma4_chan* chan = OMAP_DMA_CHANNEL_NUM;
    642         unsigned mmc_stat;
    643         ulong start;
    644         int ret = 0;
    645         start = get_timer(0);
    646         while(1) {
    647                 mmc_stat = readl(&mmc_base->stat);
    648
    649                 if (get_timer(0) - start > 10 * MAX_RETRY_MS) {
    650                         printf("%s: timed out waiting for status!\n",
    651                                         __func__);
    652                         ret = TIMEOUT;
    653                         break;
    654                 }
    655
    656                 if ((mmc_stat & ERRI_MASK) != 0) {
    657
    658                         printf("%s: mmc error status reported!\n",
    659                                         __func__);
    660                         ret = 1;
    661                         break;
    662                 }
    663
    664                 if (mmc_stat & TC_MASK) {
    665                         writel(mmc_stat | TC_MASK, &mmc_base->stat);
    666                         break;
    667                 }
    668         }
    669
    670         writel(0, &chan->ccr);
    671         return ret;
    672 }
    673 #endif



    I have highlighted the code where I'm getting the error.

    Kindly help me resolve this issue.

    Thanks

    ramappa

  • Hi Ramappa,

    Thanks for the code, of which I unfortunately can't extract the changes towards the original code.

    Yordan posted in your other thread:

    "Looking the GLSDK 6_03 u-boot sources I found the following guidance about using caches in u-boot:
    "- A suitable buffer can be alloced on the stack using the
      ALLOC_CACHE_ALIGN_BUFFER macro."
    Have you tried allocating a buffer using the ALLOC_CACHE_ALIGN_BUFFER macro? The complete document is called README.arm-caches and is located in u-boot/doc folder. The mentioned macro & its description can be found at u-boot/include/common.h"

    As you are using a U-boot version that doesn't come w/ TI's GLSDK, it is difficult to determine if the code is actually working. I strongly suggest you to start your tests w/ the U-boot sources coming w/ the latest GLSDK 6.03.00.01. In this version, activate the MMC DMA feature and see if the error persists.

    Regards,
    Marc

  • Hi Marc,

    To download all the sources I followed the following link.

    http://www.omappedia.org/wiki/6AJ.1.2_Release_Notes

    In that u-boot release I have made changes. Changes are already there above reply.

    Let me know if you need any other details.

    Thanks

    Ramappa

  • Hi Ramappa,

    okay, this is important information - you're going for Android, not for native Linux, right?

    In the meantime I have checked native DMA support for MMC in U-boot, and unfortunately, this isn't supported in the GLSDK version, sorry for the confusion.

    If I am right, your DMA transfer is initially requested by drivers/mmc/mmc.c:mmc_read_blocks() and comes from a call to disk_read() for fat filesystem (fs/fat/fat.c:do_fat_read_at() - please confirm) - but the buffer there seems to be aligned already (global variable do_fat_read_at_block in fs/fat/fat.c), although I am not that familiar w/ this - please check these locations.

    Maybe you can try flushing the whole cache just to see if it is working then - then you'd at least know that it there a cache alignment problem as I supposed earlier in this thread.

    Regards,
    Marc

  • Hi Marc,

    I have tried following cases after reading the cache document.

    Note : I'm reading from the mmc using fatload command.


    case 1 : I have tried  invalidating the complete D- Cache

    Result : Not working.   Error : mmc partition not found.

    case 2 : I have tried invalidating the complete D- Cache & I - Cache

    Result : Working.  

    Problem : It will work with almost all cases.

    Drawback : when I'm  writing new u-boot.img, that time it will not write that to flash, it will fail.

    after that  "loady" command will fail every time.

    After some analysis, I'm assuming that.

    UART is also using the DMA. when I'm invalidating complete D-cache & I-cache, It is affecting this.



    Is this conclusion is correct or tell me why that loady is failing.

    is it really cache coherency issue or something else.

    Kindly help me to resolve this issue.

    Thanks

    Ramappa