⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tffsarch.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 5 页
字号:
        }    }}/*-----------------------------------------------------------------------* *                                                                       * *                    t f f s _ d m a _ r e l e a s e                    * *                                                                       * * Release all previously allocated DMA resources (channel, intermediate * * DMA buffer etc.). For OMAP1610 (H2) board.                            * *                                                                       * *-----------------------------------------------------------------------*/static void tffs_dma_release(void){    /* if previously was allocated, release DMA channel */    if (tffsInfo.channel == 0)    {        omap_free_dma (dma_regs);        dma_regs = NULL;        tffsInfo.channel = -1;    }    /* if previously was allocated, release intermediate DMA buffer */    if (tffsInfo.dma_buf_vptr != NULL)    {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)        consistent_free (tffsInfo.dma_buf_vptr, PAGE_SIZE, tffsInfo.dma_buf_paddr);#else        dma_free_coherent (NULL, PAGE_SIZE, tffsInfo.dma_buf_vptr, tffsInfo.dma_buf_paddr);#endif        tffsInfo.dma_buf_vptr = NULL;    }}/*-----------------------------------------------------------------------* *                                                                       * *                    _ _ d m a s w _ b r e a d                          * *                                                                       * * Transfer data from DiskOnChip's I/O reguster to RAM buffer.           * * Example implementation For Texas Instruments OMAP1610 H2 board.       * *                                                                       * * Parameters:                                                           * *      off            offset of DiskOnChip's I/O register from the base * *                     of DiskOnChip window                              * *      vbuf           virtual address of RAM buffer                     * *      bytes          bytes to transfer                                 * *                                                                       * *-----------------------------------------------------------------------*/staticvoid __dmasw_bread ( int            off,                     void         * vbuf,                      unsigned int   bytes ){    register u32  tmp;    register int  waiting;    profiling[2]++;    /* Channel Source/Destination Parameters.     * Specify 16-bit port width, EMIFS source, allow source packing,     * 4-words burst allowed for source, EMIFF destination. allow     * destination packing, 4-words burst allowed for destination.     */    dma_regs->csdp =    (BURST_4 << 14)   |    /* dest.: use 4-word burst      */                        DCSDP_DST_PACK    |    /* pack dest.                   */                        (PORT_EMIFF << 9) |    /* dest. is EMIFF (RAM)         */                        (BURST_4 <<  7)   |    /* source: use 4-word burst     */                        DCSDP_SRC_PACK    |    /* pack source                  */                        (PORT_EMIFS << 2) |    /* source is EMIFS (DiskOnChip) */                        DATA_TYPE_S16;         /* 16-bit data path             */    /* Channel Control Register.     * Specify no synchronization, no OMAP 3.0/3.1 compatibility, no     * frame synchronization, high priority, constant source address,     * post-increment destination address.     */     dma_regs->ccr = (AMODE_POST_INC << 14) | /* dest (RAM): post-increment        */                    (AMODE_CONST << 12)    | /* source (DiskOnChip) : const addr. */                     DCCR_N31COMP          | /* no OMAP 3.0/3.1 compatibility     */                     DCCR_PRIO;              /* high priority */     /* Channel Frame Number Register.      * We assume that frame consists of single element, and element     * consists of single 16-bit word.     */    dma_regs->cfn = (bytes / sizeof(u16));    /* Channel Source Start Address Registers. This would be DiskOnChip's     * I/O register which is located at offset 'off' from the DiskOnChip's     * base address as specified by tffs_addr[0]).     */    tmp = tffs_addr[0] + off;    dma_regs->cssa_u = (tmp >> 16);    dma_regs->cssa_l = (tmp & 0xffff);    /* Channel Destination Start Address Registers */    if (tffs_dma_mode & 4) /* do DMA transfer directly into 'vbuf' */    {         if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */        {            tmp = __pa (vbuf);        }        else                                      /* 'vbuf' is in high memory */        {            char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) +                                          ((unsigned long)vbuf & (PAGE_SIZE - 1));            tmp = __pa (k_vbuf);        }        /* write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */#if 1           /* D-cache only. Possible options:         *   flush_dcache_range((unsigned long)vbuf, (unsigned long)(vbuf + bytes));    ARM/PPC         *   consistent_sync(vbuf, bytes, PCI_DMA_BIDIRECTIONAL);                       ARM/PPC         *   dma_cache_wback_inv((unsigned long)vbuf, (unsigned long)bytes);            MIPS/PPC/SH/x86         */        flush_dcache_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes));#else           /* both D- and I-caches */        cpu_cache_clean_invalidate_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes), 1);#endif    }    else /* transfer into intermediate DMA buffer */    {        tmp = tffsInfo.dma_buf_paddr;    }    dma_regs->cdsa_u = (tmp >> 16);    dma_regs->cdsa_l = (tmp & 0xffff);    /* start DMA channel */    dma_regs->ccr |= DCCR_EN;    /* wait for DMA transfer to finish */    for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */    {        if (((tmp = dma_regs->ccr) & DCCR_EN) == 0)        {            /* read Channel Status Register to clear it */            if (((tmp = dma_regs->csr) & DCSR_ERROR) == 0)            {                /* DMA transfer completed, move data from the intermediate DMA                 * buffer to the destination buffer (in case it was used).                 */                if ((tffs_dma_mode & 4) == 0)                    memcpy (vbuf, tffsInfo.dma_buf_vptr, bytes);            }            else /* andrayk June 13 2006: DMA transfer failed, find way to let MTD know this */            {                 PrintkError ("Bus error, DMA transfer failed");            }            return;        }    }    PrintkError ("DMA transfer timed out");}/*-----------------------------------------------------------------------* *                                                                       * *                    _ _ d m a s w _ b w r i t e                        * *                                                                       * * Transfer data from RAM buffer to DiskOnChip's I/O reguster.           * * Example implementation For Texas Instruments OMAP1610 H2 board.       * *                                                                       * * Parameters:                                                           * *      off            offset of DiskOnChip's I/O register from the base * *                     of DiskOnChip window                              * *      vbuf           virtual address of RAM buffer                     * *      bytes          bytes to transfer                                 * *                                                                       * *-----------------------------------------------------------------------*/staticvoid __dmasw_bwrite ( int            off,                      void         * vbuf,                       unsigned int   bytes ){    register u32  tmp;    register int  waiting;    profiling[3]++;    /* Channel Source/Destination Parameters.     * Specify 16-bit port width, EMIFF source, allow source packing,     * 4-words burst allowed for source, EMIFS destination. allow     * destination packing, 4-words burst allowed for destination.     */    dma_regs->csdp =    (BURST_4 << 14)   |    /* dest.: use 4-word burst     */                        DCSDP_DST_PACK    |    /* pack dest.                  */                        (PORT_EMIFS << 9) |    /* dest. is EMIFS (DiskOnChip) */                        (BURST_4 <<  7)   |    /* source: use 4-word burt     */                        DCSDP_SRC_PACK    |    /* pack source                 */                        (PORT_EMIFF << 2) |    /* source is EMIFF (RAM)       */                        DATA_TYPE_S16;         /* 16-bit data path            */    /* Channel Control Register.     * Specify no synchronization, no OMAP 3.0/3.1 compatibility, no     * frame synchronization, high priority, constant dest. address,     * post-increment source address.     */     dma_regs->ccr = (AMODE_CONST << 14)    | /* dest. (DiskOnChip): const addr. */                    (AMODE_POST_INC << 12) | /* source (RAM): post-increment    */                     DCCR_N31COMP          | /* no OMAP 3.1/3.0 compatibility   */                     DCCR_PRIO;              /* high priority */    /* Channel Frame Number Register.     * We assume that frame consists of single elemnt, and element consists     * of single 16-bit word.     */    dma_regs->cfn = (bytes / sizeof(u16));    /* Channel Source Start Address Registers */    if (tffs_dma_mode & 4) /* do DMA transfer directly from 'vbuf' */    {        /* Write (if dirty) contents of 'vbuf' from CPU D-cache to RAM.         * Possible options:         *   clean_dcache_range((unsigned long)vbuf, (unsigned long)(vbuf + bytes));    ARM/PPC         *   consistent_sync(vbuf, bytes, PCI_DMA_TODEVICE);                            ARM/PPC         *   dma_cache_wback((unsigned long)vbuf, (unsigned long)bytes);                MIPS/PPC/SH/x86         */        clean_dcache_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes));        if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */        {            tmp = __pa (vbuf);        }        else                                      /* 'vbuf' is in high memory */        {            char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) +                                          ((unsigned long)vbuf & (PAGE_SIZE - 1));            tmp = __pa (k_vbuf);        }    }    else                   /* use intermediate DMA buffer */    {        /* move data from RAM buffer to the intermediate DMA buffer */        memcpy (tffsInfo.dma_buf_vptr, vbuf, bytes);        tmp = tffsInfo.dma_buf_paddr;    }    dma_regs->cssa_u = (tmp >> 16);    dma_regs->cssa_l = (tmp & 0xffff);    /* Channel Destination Start Address Regist.This would be DiskOnChip's     * I/O register which is located at offset 'off' from the DiskOnChip's     * base address as specified by tffs_addr[0]).     */    tmp = tffs_addr[0] + off;    dma_regs->cdsa_u = (tmp >> 16);    dma_regs->cdsa_l = (tmp & 0xffff);    /* start DMA channel */    dma_regs->ccr |= DCCR_EN;    /* poll DMA channel's status register for end of DMA transfer */    for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */    {        if (((tmp = dma_regs->ccr) & DCCR_EN) == 0)        {            if ((tmp = dma_regs->csr) & DCSR_ERROR) /* andrayk June 14 2006: DMA transfer failed, find way to let MTD know this */            {                 PrintkError ("Bus error, DMA transfer failed");            }            return;        }    }    PrintkError ("DMA transfer timed out");}#elif defined(CONFIG_ARCH_OMAP24XX)/*_____________________________________________________________________________ |                                                                            | |                                                                            | |                Texas Instruments OMAP-2420 (H4) board                      | |                                                                            | |____________________________________________________________________________| */# include <asm/arch/hardware.h># include <asm/arch/dma.h>/* # include <asm/arch/pm_prcm.h> */  /* conflicts with <asm/arch/hardware.h> */# include <asm/arch/gpio.h># include <asm/arch/mux.h>/* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears * to be buggy: it seems to constantly shoot past the end of the address * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some * bogus data into this RAM address range while invalidating it in D-cache.  */# define OMAP2420_DCACHE_BUG_WORKAROUND# ifndef OMAP_DMA4_CCR_EN#   define OMAP_DMA4_CCR_EN   (1 << 7)# endif# define GPMC_CONFIG1_CS2  0xC0                         /* phys. addr. 0x6800A0C0 */# define GPMC_CONFIG2_CS2  (GPMC_CONFIG1_CS2 +  0x4)    /* phys. addr. 0x6800A0C4 */# define GPMC_CONFIG3_CS2  (GPMC_CONFIG1_CS2 +  0x8)    /* phys. addr. 0x6800A0C8 */# define GPMC_CONFIG4_CS2  (GPMC_CONFIG1_CS2 +  0xC)    /* phys. addr. 0x6800A0CC */# define GPMC_CONFIG5_CS2  (GPMC_CONFIG1_CS2 + 0x10)    /* phys. addr. 0x6800A0D0 */# define GPMC_CONFIG6_CS2  (GPMC_CONFIG1_CS2 + 0x14)    /* phys. addr. 0x6800A0D4 */# define GPMC_CONFIG7_CS2  (GPMC_CONFIG1_CS2 + 0x18)    /* phys. addr. 0x6800A0D8 *//* layout of DMA channel's registers */typedef struct {    volatile u32  ccr;     /* Channel Control Register                */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -