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

📄 tffsarch.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 5 页
字号:
    volatile u32  clnk;    /* Channel Link Control                    */    volatile u32  cicr;    /* Channel Interrupt Control Register      */    volatile u32  csr;     /* Channel Status Register                 */    volatile u32  csdp;    /* Channel Source / Destination Parameters */    volatile u32  cen;     /* Channel Element Number                  */    volatile u32  cfn;     /* Channel Frame Number                    */    volatile u32  cssa;    /* Channel Source Start Address            */    volatile u32  cdsa;    /* Channel Destination Start Address       */    volatile u32  csei;    /* Channel Source Element Index            */    volatile u32  csfi;    /* Channel Source Frame Index              */    volatile u32  cdei;    /* Channel Destination Element Index       */    volatile u32  cdfi;    /* Channel Destination Frame Index         */    volatile u32  csac;    /* Channel Source Address Counter          */    volatile u32  cdac;    /* Channel Destination Address Counter     */    volatile u32  ccen;    /* Channel Current Element Number          */    volatile u32  ccfn;    /* Channel Current Frame Number            */} __dma_reg_t;/* * static routines for OMAP2420 */static void tffs_dma_init (int resume);static void tffs_dma_release (void);/* * static vars */static __dma_reg_t * dma_regs_vptr = NULL;void omap24xx_enable_gpio_irq (int gpio_irq, int enable){    register u32 gpio_line = gpio_irq - IH_GPIO_BASE;     register u32 bit       = OMAP_GPIO_BIT(gpio_line);    register u32 base_reg  = OMAP_GPIO_BASE_REG(gpio_line);    unsigned int val       = 0;    if (enable == TRUE)    {        writel (bit, (base_reg + OMAP2420_GPIO_SET_IRQENABLE1));        __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */        omap_set_gpio_edge_ctrl (gpio_line, OMAP_GPIO_LEVEL_LOW);    }    else    {        omap_set_gpio_edge_ctrl (gpio_line, 0);        writel (bit, (base_reg + OMAP2420_GPIO_CLEAR_IRQENABLE1));        __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */        writel (bit, (base_reg + OMAP2420_GPIO_IRQSTATUS1));        __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */    }}/*-----------------------------------------------------------------------* *                                                                       * *                    t f f s a r c h _ i n i t                          * *                                                                       * * This routine is called during module initialization time with 'resume'* * argument set to FALSE, and from Power Manager's 'resume' routine with * * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine     * * allocates and initializes all required board resources; if 'resume'   * * is TRUE, this routine does minimal required re-initialization of      * * these resources after power suspend. For OMAP2420 (H4) board.         * *                                                                       * * Parameters:                                                           * *      suspend     FALSE (module initialization) or TRUE (power resume) * *                                                                       * * Returns:                                                              * *      always '1' (success)                                             * *                                                                       * *-----------------------------------------------------------------------*/unsigned char tffsarch_init (int resume){    register int  tmp;    char        * vp;    if ((vp = (char *)ioremap_nocache(OMAP2420_GPMC_BASE, PAGE_SIZE)) == NULL)    {        PrintkError ("ioremap_nocache failed");    }    else    {        /* Configure Chip Select that DiskOnChip is connected to.         *          * NOTE. Code below configures Chip Select to set duration of         *       DiskOnChip access cycle to 65 nanosecond, which is         *       appropriate for the case when DiskOnChip is connected to         *       OMAP2420 board via M-Systems' adapters. If you solder         *       DiskOnChip into your board, consider changing Chip Select         *       settings to significantly shorten DiskOnChip acecss cycle.         *       This should have significant positive efefct on         *       DiskOnChip's 'read' performance.         */        tmp = (0 << 31) |  /* synchronous wrapping burst not supported */              (0 << 30) |  /* single access */              (0 << 29) |  /* asynchronous read */              (0 << 28) |  /* single access */              (0 << 27) |  /* write asynchronous */              (0 << 25) |  /* start access time at first rising edge of GPMC.CLK */              (0 << 23) |  /* burst length 4 words */              (0 << 22) |  /* wait pin not monitored for read access */              (0 << 21) |  /* wait pin not monitored for write access */              (0 << 18) |  /* wait pin is monitored with valid data */              (0 << 16) |  /* wait input pin is WAIT0 */              (1 << 12) |  /* 16-bit device */              (0 << 10) |  /* NOR flash, pSRAM, or asynchronous device */              (1 <<  9) |  /* address/data multiplexed attached device */              (0 <<  4) |  /* x1 latencies */              (3 <<  0);   /* GPMC.CLK = GPMC_FCLK/4 */        writel (tmp /* 0x00001203 */, vp + GPMC_CONFIG1_CS2);        tmp = (6 << 16) | /* nCS assertion time for write access */              (6 <<  8) | /* nCS assertion time for read access */              (0 <<  7) | /* nCS timing sygnal is not delayed */              (0 <<  0);  /* nCS assertion time */        writel (tmp /* 0x00060600 */, vp + GPMC_CONFIG2_CS2);        tmp = (1 << 16) | /* nADV deassertion time for write access */              (1 <<  8) | /* nADV deassertion time for read access */              (0 <<  7) | /* nADV timing control sygnal is not delayed */              (0 <<  0);  /* nADV assertion time */        writel (tmp /* 0x00010100 */, vp + GPMC_CONFIG3_CS2);        tmp = (5 << 24) | /* nWE deassertion time */              (0 << 23) | /* nWE timing control sygnal is not delayed */              (2 << 16) | /* nWE assertion time */              (6 <<  8) | /* nOE deassertion time */              (0 <<  7) | /* nOE timing control sygnal is not delayed */              (2 <<  0);  /* nOE assertion time */        writel (tmp /* 0x05020602 */, vp + GPMC_CONFIG4_CS2);        tmp = (1 << 24) | /* delay between successive words in multiple access */              (5 << 16) | /* delay between start-cycle and first data valid */              (7 <<  8) | /* total write cycle time in GPMC_FCLK cycles */              (7 <<  0);  /* total read cycle time in GPMC_FCLK cycles */        writel (tmp /* 0x01050707 */, vp + GPMC_CONFIG5_CS2);        /* Map Chips Select CS2 at physical address 0x10000000 (as         * specified by macro TFFS_PHYS_ADDR).         */        tmp = 0x00000F50;        writel (tmp, vp + GPMC_CONFIG7_CS2);        iounmap (vp);    }    if (tffs_irq >= 0)    {        register int gpio_line = (tffs_irq - IH_GPIO_BASE);        if( omap_request_gpio(gpio_line) == 0 )        {            register u8 x = readb (OMAP24XX_VA_SYSTEM_CONTROL_BASE + 0x10c);            /* set GPIO function (mux mode 3), disable pullup/pulldown */            x &= ~(MUXMODE_MASK);            x |= 3;            x &= ~(PULL_UD_ENABLE_MASK);            writeb (x, OMAP24XX_VA_SYSTEM_CONTROL_BASE + 0x10c);            /* configure this GPIO line as input */            omap_set_gpio_direction (gpio_line, TRUE);            /* configure GPIO interrupt as level-low for this GPIO line */#if 0            omap_set_gpio_edge_ctrl (gpio_line, /* OMAP_GPIO_LEVEL_LOW */ OMAP_GPIO_FALLING_EDGE);#endif        }        else        {            PrintkWarning ("failed to get IRQ %d", tffs_irq);            tffs_irq = -1;        }    }    /* if DMA is requested, configure it */    if (tffs_dma_mode > 0)    {        tffs_dma_init (resume);    }    return 1;}void TffsHWRelease(void){    /* if DMA was actually used, release all DMA resources */    if (tffs_dma_mode > 0)    {        tffs_dma_release ();    }    /* if IRQ was actually used, release respective GPIO resources */    if (tffs_irq >= 0)    {        register int gpio_line = (tffs_irq - IH_GPIO_BASE);        omap_free_gpio (gpio_line);    }}/*-----------------------------------------------------------------------* *                                                                       * *                    t f f s _ d m a _ i n i t                          * *                                                                       * * This routine is called during module initialization time with 'resume'* * argument set to FALSE, and from Power Manager's 'resume' routine with * * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine     * * allocates and initializes all required DMA resources; if 'resume' is  * * TRUE, this routine does minimal required re-initialization of DMA     * * channel after power suspend. For OMAP2420 (H4) board.                 * *                                                                       * * Parameters:                                                           * *      suspend     FALSE (module initialization) or TRUE (power resume) * *                                                                       * *-----------------------------------------------------------------------*/static void tffs_dma_init (int resume){    register u32  tmp;    int           rc;    if (resume == FALSE)     {        /* We use single DMA channel for both 'read' and 'write' operations,         * so we allocate it here. We don't use DMA interrupts, so we won't         * need DMA callback.         */        rc = omap_request_dma (0,                               TFFS_DEVICE_NAME,                               NULL,        /* no callback when DMA completes */                               NULL,        /* data to pass to DMA callback   */                               &tffsInfo.channel);        if ((rc != 0) || (tffsInfo.channel < 0) ||                          (tffsInfo.channel >= OMAP24XX_LOGICAL_DMA_CH_COUNT))        {            /* failed to allocate DMA channel, won't use DMA */            tffs_dma_mode = 0;            PrintkError ("can't get DMA chan");            return;        }        else        {             PrintkInfo ("use DMA channel %d", tffsInfo.channel);             /* virt. address of DMA channel's register set */            dma_regs_vptr = (__dma_reg_t *)                (OMAP_DMA4_BASE + (0x60 * tffsInfo.channel) + 0x80);        }    }    /* Channel Control Register */    tmp =  (0 << 25) |     /* buffering enabled                    */           (0 << 24) |     /* destination triggers DMA request     */           (1 << 23) |     /* prefetch enabled                     */           (0 << 21) |     /* secure mode disabled                 */           (0 << 19) |     /* no synchronization                   */           (1 << 18) |     /* block synchronization                */           (0 << 17) |     /* transaparent copy disabled           */           (0 << 16) |     /* constant fill disabled               */           (1 << 14) |     /* post-increment destination address   */           (0 << 12) |     /* constant source address              */           (0 <<  8) |     /* ignore MSUSPEND                      */           (0 <<  7) |     /* channel disabled (stopped)           */           (1 <<  6) |     /* high priority channel                */           (0 <<  5) |     /* no frame synchronization             */           (0 <<  0);      /* no synchronization (i.e. s/w DMA)    */    writel (tmp, &dma_regs_vptr->ccr);    /* Channel Frame Number Register.      * We assume that frame consists of single element.     */    writel (1, &dma_regs_vptr->cfn);    /* Channel Interrupt Control Register.     * Disable all interrupts - we will be polling DMA controller.     */    tmp = /* OMAP_DMA_DROP_IRQ  | */ /* synchronization drop     */          /* OMAP_DMA_BLOCK_IRQ | */ /* end-of-block interrupt   */          /* (1 << 11)          | */ /* misaligned address error */          /* (1 <<  8)          | */ /* transaction error        */          0;    writel (tmp, &dma_regs_vptr->cicr);    /* Channel Status Register.     * Write all-ones to clear any pending interrupts.     */    writel (~0, &dma_regs_vptr->csr);    if (resume == FALSE)    {        tffsInfo.dma_buf_vptr = NULL;        tffsInfo.dma_buf_size = 0;        if ((tffs_dma_mode >= 1)#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || !defined(OMAP2420_DCACHE_BUG_WORKAROUND)                                 && (tffs_dma_mode <= 3)#endif           )        {            /* allocate intermediate DMA buffer (we assume one MMU page

⌨️ 快捷键说明

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